Easy

题目描述

给定一个日期,返回该日期是一周中的第几天。

输入为三个整数,分别表示日、月、年。

返回答案为以下值之一:{“Sunday”, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”}。

注意:1971年1月1日是星期五。

示例 1:

输入:day = 31, month = 8, year = 2019
输出:"Saturday"

示例 2:

输入:day = 18, month = 7, year = 1999
输出:"Sunday"

示例 3:

输入:day = 15, month = 8, year = 1993
输出:"Sunday"

约束条件:

  • 给定的日期是1971年到2100年之间的有效日期。

提示:

  • 计算给定年份之前所有年份的天数总和
  • 处理闰年的情况
  • 计算给定年份中每个月的天数

解题思路

这道题需要计算从1971年1月1日(星期五)到给定日期之间经过了多少天,然后通过模7运算确定星期几。

主要思路:

  1. 累加年份天数:计算从1971年到给定年份前一年的所有天数
  2. 处理闰年:需要正确判断闰年(能被4整除但不能被100整除,或能被400整除)
  3. 累加月份天数:计算给定年份中从1月到给定月份前一个月的所有天数
  4. 加上当前天数:加上给定的日期
  5. 模7运算:由于1971年1月1日是星期五(索引为5),最终结果需要加5再模7

优化方法:

  • 可以使用数学公式(如蔡勒公式)直接计算,但累加方法更直观易懂
  • 预先定义每月天数数组,简化代码

这种方法时间复杂度为O(年份差值),对于题目给定范围完全够用。

代码实现

class Solution {
public:
    string dayOfTheWeek(int day, int month, int year) {
        vector<string> days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
        vector<int> monthDays = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        
        int totalDays = 0;
        
        // 计算从1971年到year-1年的总天数
        for (int y = 1971; y < year; y++) {
            if (isLeapYear(y)) {
                totalDays += 366;
            } else {
                totalDays += 365;
            }
        }
        
        // 计算当前年份从1月到month-1月的总天数
        for (int m = 1; m < month; m++) {
            totalDays += monthDays[m];
            if (m == 2 && isLeapYear(year)) {
                totalDays += 1;
            }
        }
        
        // 加上当前月份的天数
        totalDays += day - 1;
        
        // 1971年1月1日是星期五(索引5)
        return days[(totalDays + 5) % 7];
    }
    
private:
    bool isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }
};
class Solution:
    def dayOfTheWeek(self, day: int, month: int, year: int) -> str:
        days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
        month_days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        
        def is_leap_year(y):
            return (y % 4 == 0 and y % 100 != 0) or (y % 400 == 0)
        
        total_days = 0
        
        # 计算从1971年到year-1年的总天数
        for y in range(1971, year):
            if is_leap_year(y):
                total_days += 366
            else:
                total_days += 365
        
        # 计算当前年份从1月到month-1月的总天数
        for m in range(1, month):
            total_days += month_days[m]
            if m == 2 and is_leap_year(year):
                total_days += 1
        
        # 加上当前月份的天数
        total_days += day - 1
        
        # 1971年1月1日是星期五(索引5)
        return days[(total_days + 5) % 7]
public class Solution {
    public string DayOfTheWeek(int day, int month, int year) {
        string[] days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
        int[] monthDays = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        
        int totalDays = 0;
        
        // 计算从1971年到year-1年的总天数
        for (int y = 1971; y < year; y++) {
            if (IsLeapYear(y)) {
                totalDays += 366;
            } else {
                totalDays += 365;
            }
        }
        
        // 计算当前年份从1月到month-1月的总天数
        for (int m = 1; m < month; m++) {
            totalDays += monthDays[m];
            if (m == 2 && IsLeapYear(year)) {
                totalDays += 1;
            }
        }
        
        // 加上当前月份的天数
        totalDays += day - 1;
        
        // 1971年1月1日是星期五(索引5)
        return days[(totalDays + 5) % 7];
    }
    
    private bool IsLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }
}
var dayOfTheWeek = function(day, month, year) {
    const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    const date = new Date(year, month - 1, day);
    return days[date.getDay()];
};

复杂度分析

复杂度类型大小说明
时间复杂度O(year - 1971)需要遍历从1971年到给定年份的所有年份
空间复杂度O(1)只使用常量额外空间