Easy

题目描述

给你一个字符串 date,它是一个按照格式 YYYY-MM-DD 表示的格里高利历日期,返回该日期是一年中的第几天。

示例 1:

输入:date = "2019-01-09"
输出:9
解释:给定日期是2019年的第9天。

示例 2:

输入:date = "2019-02-10"
输出:41

约束条件:

  • date.length == 10
  • date[4] == date[7] == '-',其他的 date[i] 都是数字
  • date 表示的范围从 1900 年 1 月 1 日到 2019 年 12 月 31 日

提示:

  • 可以使用一个整数数组来存储每个月的天数。如果是闰年,二月会多一天。然后,我们可以手动计算序数:当前月的天数 +(该月之前所有月份的天数)。

解题思路

这道题要求计算给定日期是一年中的第几天。我们可以采用以下思路:

方法一:累加计算

  1. 解析输入字符串,提取年、月、日信息
  2. 预先定义每个月的天数数组
  3. 判断是否为闰年,如果是闰年且已经过了2月,需要额外加1天
  4. 累加目标月份之前所有月份的天数,再加上当前月的天数

闰年判断规则:

  • 能被400整除,或者能被4整除但不能被100整除

方法二:使用内置日期库 某些语言提供了日期处理库,可以直接计算,但为了算法练习,建议使用方法一。

这道题的关键在于正确处理闰年的情况。实现时需要注意字符串解析和边界条件的处理。

时间复杂度为O(1),因为最多只需要遍历12个月;空间复杂度也是O(1),只需要常数级别的额外空间。

代码实现

class Solution {
public:
    int dayOfYear(string date) {
        int year = stoi(date.substr(0, 4));
        int month = stoi(date.substr(5, 2));
        int day = stoi(date.substr(8, 2));
        
        vector<int> days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        
        // 判断是否为闰年
        bool isLeapYear = (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
        if (isLeapYear) {
            days[1] = 29;
        }
        
        int result = day;
        for (int i = 0; i < month - 1; i++) {
            result += days[i];
        }
        
        return result;
    }
};
class Solution:
    def dayOfYear(self, date: str) -> int:
        year, month, day = map(int, date.split('-'))
        
        days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        
        # 判断是否为闰年
        is_leap_year = (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0)
        if is_leap_year:
            days[1] = 29
        
        return day + sum(days[:month-1])
public class Solution {
    public int DayOfYear(string date) {
        string[] parts = date.Split('-');
        int year = int.Parse(parts[0]);
        int month = int.Parse(parts[1]);
        int day = int.Parse(parts[2]);
        
        int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        
        // 判断是否为闰年
        bool isLeapYear = (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
        if (isLeapYear) {
            days[1] = 29;
        }
        
        int result = day;
        for (int i = 0; i < month - 1; i++) {
            result += days[i];
        }
        
        return result;
    }
}
/**
 * @param {string} date
 * @return {number}
 */
var dayOfYear = function(date) {
    const [year, month, day] = date.split('-').map(Number);
    const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    
    if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
        daysInMonth[1] = 29;
    }
    
    let dayOfYear = day;
    for (let i = 0; i < month - 1; i++) {
        dayOfYear += daysInMonth[i];
    }
    
    return dayOfYear;
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(1)最多遍历12个月,常数时间
空间复杂度O(1)只使用了固定大小的数组和几个变量