LeetCode 1154. 一年中的第几天
题目描述

题意分析
给定合法日期字符串
YYYY-MM-DD,返回它在这一年中是第几天。天数从 $1$ 开始计数,因此只需累计当年已经完整经过的月份,再加上当前月的日号,不需要累计之前的年份。
解法:月份天数累加
核心思路
[!blue]
设日期的月、日分别为
month、day,答案就是前month - 1个月的总天数加day。当前月尚未完整经过,不能把它的整个月长也加进去。先用一个长度为 $12$ 的数组保存平年每个月的天数,数组下标比月份小一。只有二月会受年份影响:能被 $400$ 整除,或能被 $4$ 整除但不能被 $100$ 整除的年份是闰年,将
days[1]改为 $29$。其余月份保持不变。日期格式固定,因此年份读取下标区间
[0, 4),月份读取[5, 7),日号读取[8, 10),自然跳过两个连字符。parseNumber从左到右读数字,每次用“已有值乘十,再加当前数字”累积成整数,月份和日号的前导零也会自然处理。将
answer初始化为day,再累加days[0]到days[month - 2]。一月时循环不执行,答案就是日号;日期在二月时,闰日已由合法日号表示,不需另外加一;只有月份超过二月,累加二月整月时才会用到调整后的 $29$ 天。
解题步骤
- 按固定下标区间解析
year、month、day。- 初始化平年月长数组;若为闰年,将二月天数改为 $29$。
- 令
answer = day,遍历i < month - 1的月份下标并累加天数。- 返回
answer。
代码实现
class Solution {
public int dayOfYear(String date) {
int year = parseNumber(date, 0, 4);
int month = parseNumber(date, 5, 7);
int day = parseNumber(date, 8, 10);
int[] days = {
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
};
// 先确定二月月长,后面的累加不再区分闰年。
if (isLeapYear(year)) {
days[1] = 29;
}
int answer = day;
// 当前月只算已经过的日期,循环仅累加前面的整月。
for (int i = 0; i < month - 1; i++) {
answer += days[i];
}
return answer;
}
private int parseNumber(String date, int start, int end) {
int value = 0;
for (int i = start; i < end; i++) {
value = value * 10 + date.charAt(i) - '0';
}
return value;
}
private boolean isLeapYear(int year) {
return year % 400 == 0 || year % 4 == 0 && year % 100 != 0;
}
}
func dayOfYear(date string) int {
year := parseNumber(date, 0, 4)
month := parseNumber(date, 5, 7)
day := parseNumber(date, 8, 10)
days := []int{
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31,
}
// 先确定二月月长,后面的累加不再区分闰年。
if isLeapYear(year) {
days[1] = 29
}
answer := day
// 当前月只算已经过的日期,循环仅累加前面的整月。
for i := 0; i < month-1; i++ {
answer += days[i]
}
return answer
}
func parseNumber(date string, start int, end int) int {
value := 0
for i := start; i < end; i++ {
value = value*10 + int(date[i]-'0')
}
return value
}
func isLeapYear(year int) bool {
return year%400 == 0 || year%4 == 0 && year%100 != 0
}
复杂度分析
- 时间复杂度:$O(1)$,固定长度输入,最多累计11个月。
- 空间复杂度:$O(1)$,12个月长与解析变量。
关键点总结
[!green]
- 当前月只加已经经过的日期,不加完整月长。
- 闰年的额外一天仅在二月之后影响累加结果。
易错点总结
[!yellow]
- 只判断能被 $4$ 整除,会把不能被 $400$ 整除的整百年份误判为闰年。
- 累加到当前月,会多算整月。
- 共享并修改二月月长却不恢复,会让下次平年计算沿用29天。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 1118. 一月有多少天 | 简单 | 先确定各月天数及闰年二月长度,再累加当前月份之前的天数。 |
| 1360. 日期之间隔几天 | 简单 | 原题计算两个日期间隔,可先把每个日期映射成统一的累计天数。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!