当前位置: 首页 > news >正文

百炼OJ算法刷题:日期算法错题本Vol.8-2964:日历问题

前言:

在算法题里,有一类题几乎每个人都会遇到:

日期 / 星期计算题。

给你一个起始日期和若干天数,让你求最终的年月日与星期。

乍一看很简单,但真正写代码的时候就会发现问题:

  • 闰年规则

  • 不同月份天数

  • 星期循环

  • 年份变化

  • 日期边界

这些细节如果处理不好,程序就会出错。

这类题其实是一个非常典型的“时间模拟问题”
它不仅考察代码能力,更考察对时间结构的建模能力

这篇文章记录了我完整解决日历问题(POJ 2964)的思考过程。


一、题目回顾:日历问题

题目描述

在我们现在使用的日历中:

  • 闰年:能被 4 整除

  • 但能被 100 整除而不能被 400 整除的不是闰年

例如:

年份是否闰年
1600
1700
1800
1900
2000

现在给定:

从 2000 年 1 月 1 日开始经过的天数。

要求输出:

YYYY-MM-DD DayOfWeek

其中 DayOfWeek 为:

Sunday Monday Tuesday Wednesday Thursday Friday Saturday

已知:

2000-01-01 是 Saturday

输入格式

多组数据,每行一个整数:

days

最后一行:

-1

输出格式

YYYY-MM-DD DayOfWeek

样例输入

1730 1740 1750 1751 -1

样例输出

2004-09-26 Sunday 2004-10-06 Wednesday 2004-10-16 Saturday 2004-10-17 Sunday

二、直觉解法:时间模拟

2.1 核心思路

这类题最自然的想法是:

把时间当作一个可以逐层减少的结构。

我们从大到小处理:

天数 → 年份 → 月份 → 日期

具体流程:

1️⃣ 先减去整年的天数
2️⃣ 再减去整个月的天数
3️⃣ 剩下的就是日期

同时:

星期 = (起始星期 + 经过天数) % 7

三、关键模块拆解

为了让代码结构清晰,我们可以拆成几个函数。


3.1 判断闰年

闰年规则:

能被4整除 但能被100整除且不能被400整除的除外

代码实现:

bool leap(int y){ return (y%4==0 && y%100!=0) || (y%400==0); }

3.2 获取月份天数

不同月份天数不同。

31天:1 3 5 7 8 10 12 30天:4 6 9 11 2月:28 或 29

代码:

int mdays(int y,int m){ int d[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; if(m==2 && leap(y)) return 29; return d[m]; }

3.3 星期计算

已知:

2000-01-01 是 Saturday

我们定义星期编号:

数字星期
0Saturday
1Sunday
2Monday
3Tuesday
4Wednesday
5Thursday
6Friday

于是:

weekday = days % 7

四、完整算法流程

我们从2000-01-01开始模拟。

第一步:计算年份

循环减去年份天数:

365 或 366

直到剩余天数小于一年。


第二步:计算月份

循环减去每个月天数:

1月 → 2月 → 3月 ...

直到剩余天数小于当月天数。


第三步:计算日期

剩余天数 + 1:

day = days + 1

第四步:计算星期

weekday = total_days % 7

五、完整代码实现

#include<iostream> #include<iomanip> using namespace std; bool leap(int y){ return (y%4==0 && y%100!=0) || (y%400==0); } int mdays(int y,int m){ int d[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; if(m==2 && leap(y)) return 29; return d[m]; } int main(){ int days; string w[7]={ "Saturday","Sunday","Monday", "Tuesday","Wednesday","Thursday","Friday" }; while(cin>>days && days!=-1){ int total=days; int y=2000; while(days >= (leap(y)?366:365)){ days -= leap(y)?366:365; y++; } int m=1; while(days >= mdays(y,m)){ days -= mdays(y,m); m++; } int d=days+1; cout<<y<<"-" <<setw(2)<<setfill('0')<<m<<"-" <<setw(2)<<setfill('0')<<d<<" " <<w[total%7]<<endl; } }

六、时间复杂度分析

算法复杂度:

部分复杂度
年份循环O(年份数)
月份循环O(12)
总复杂度O(years)

由于年份最大不会超过 9999,这个复杂度完全可接受。


七、日期问题的核心模板

其实所有日期题都可以归纳为一个模板:

模板一:星期计算

weekday = (start_week + days) % 7

模板二:日期推算

while(days >= year_days) days -= year_days while(days >= month_days) days -= month_days day = days + 1

模板三:月份循环

next_month_week = (current_week + month_days) % 7

掌握这三个模板,绝大多数日历类算法题都能解决。


八、这类题的识别指南

如何一眼看出是日期模拟题

一般有以下特征:

✅ 给定某个起始日期
✅ 给定天数或时间差
✅ 要求计算未来日期
✅ 涉及闰年或星期

常见题型:

日历问题 Friday the 13th 日期推算 日期差计算

九、写在最后:时间也是一种数据结构

这道题让我第一次意识到:

时间其实也是一种结构化数据。

年份 → 月份 → 日期 → 星期

它们之间存在非常清晰的层级关系。

当我们把时间拆解成这些结构后,问题就变得非常清晰。

很多算法题其实也是这样:

  • 看似复杂

  • 其实只是结构没有拆清楚

当你建立好模型,代码就会自然出现。

http://www.jsqmd.com/news/453891/

相关文章:

  • 深聊贵阳有实力的电子商务培训学校,特色亮点全分享 - 工业品网
  • 基于Matlab的信号处理:信号波形恢复与求各阶谐波及数据拟合
  • 学长亲荐 8个降AI率软件降AIGC网站:本科生必看的深度测评与推荐
  • 测试面试最容易翻车的5种回答方式,90%的新人都踩过坑
  • Matlab Simulink电机FOC观测器模型:龙贝格观测器+PLL无传感器控制
  • 2026年遵义专业电子竞技职业培训热门推荐,哪家性价比高 - 工业品牌热点
  • AtCoder Weekday Contest 0013 Beta题解(AWC 0013 Beta A-E)
  • JavaScript在AI时代的必备价值
  • 海南货物运输品牌企业推荐,费用怎么收? - myqiye
  • LiveCharts2总结-饼图、折线图、柱状图
  • 直接上干货,咱们今天聊聊怎么用MFC撸一个自动化设备控制程序。这个项目里整合了雷塞运动卡、基恩士视觉和网络通信,核心在于各种硬件之间的指令协调
  • 详解InnoDB一次更新事务的执行过程(从SQL到磁盘落地全链路)
  • 2026冲刺用!10个降AI率软件降AIGC网站深度测评,自考必看!
  • 2026年全国知名的DCMM认证服务商排名,哪家口碑好值得推荐 - 工业推荐榜
  • 打工人必备!Openclaw实践之采集+发布小红书自动化方案,每天省下3小时!
  • 基于小波和神经网络的均衡算法及其与传统电话信道模型中神经网络盲均衡算法的Matlab仿真对比
  • 基于SpringBoot2+vue3的相亲网站
  • 2026年起帆电缆代理商怎么选择,推荐一下厂家电话 - mypinpai
  • 解决 Spring Boot 中 IDEA 下 log.info() 报错问题
  • 大模型微调完全指南:LoRA、QLoRA、全量微调怎么选?
  • [特殊字符] 深度估计 Lotus 扩散模型 高精度预测应用
  • 零基础学微信小程序前端(原生JS):从0到1写第一个可交互页面
  • python flask课程学习网站
  • 从社死边缘拯救我:用 AR 眼镜打造“亲戚称呼助手“
  • GBase 8c gsql常用元命令 详解
  • Java 17 新特性全解析:从语言增强到运行时优化
  • Docker 学习笔记
  • Leetcode第一题:用C++解决两数之和问题
  • [特殊字符]深度估计——GLPN在NYUv2上的单目深度优化模型
  • 实用工具推荐|m3u8live.cn:免安装 M3U8 在线播放器,开发调试超便捷