场景:
题目:一周中的第几天
(1)需求:给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天;输入为三个整数:day、month 和 year,分别表示日、月、年。您返回的结果必须是这几个值中的一个 {“Sunday”, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”}。
(2)示例:
示例 1:
输入:day = 31, month = 8, year = 2019
输出:“Saturday”
(3)提示:
给出的日期一定是在 1971 到 2100 年之间的有效日期;
思路:
(1)提示:了解年月日的基本信息,详见扩展;
(2)确定当前年是闰年还是非闰年(闰年可以整除4并且100或者整除400),闰年366天,非闰年365天;
(3)确定二月天数:闰年29天,非闰年28天;
(4)有效日期区间是 [1971-2100],为了在计算天数中确定闰年或非闰年,选取1970作为参照年,1970-01-01为参照日期,求传入的日期到参照日期之间的总天数;
(5)确定月数组:月输入范围为1-12,因此巧妙的将数组中下标为0的元素设置为0,下标为1的元素才是第一个月的天数;
(6)确定周数组:1970-01-01是周四,数组中存储着一周中的七天,总天数days初始化为0,那么当days = 1时,表示这一天是周四,即days = 0时表示周三,根据这一特性,巧妙的设置周数组将周三作为下标为0的元素,weeks[days%7]就可以很好的确定是周几;
(7)这个巧妙的方法来源于官方题解下一位名为 lion-girl 的用户;
扩展:
(1)一个月有28、29、30、31天;
(2)一月、三月、五月、七月、八月、十月、十二月这七个月是31天;
(3)四月、六月、九月、十一月这四个月是30天;
(4)二月的闰年是29天,非闰年是28天;
(5)农历就是阴历,阳历就是公历;
代码实现:
#include <string>
#include <sstream>
using namespace std;
class Solution
{
public:
string dayOfTheWeek(int day, int month, int year)
{
int daysOfMonth[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
string weeks[] = {"Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday"};
// 求一年中天数
int days = 0;
for (int y = 1970; y < year; y++)
{
days += isRun(y) ? 366 : 365;
}
// 更新一年中二月天数
if (isRun(year))
{
daysOfMonth[2] = 29;
}
// 求总天数
for (int m = 1; m < month; m++)
{
// 1970-01-01 + 1971-xx
days += daysOfMonth[m];
}
// 1970-01-01 + 1971-xx-xx
days += day;
// 一周中的第几天
return weeks[days % 7];
}
private:
// 是否闰年 (闰年 366天、非闰年365天)
bool isRun(int year)
{
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
};