《算法零基础100讲》(第6讲) 日期算法
零、写在前面
这是《算法零基础100讲》 专栏打卡学习的第六天了,学习算法的时候, 「 切忌心浮气躁 」 ,就像十年前的我,为了竞赛取得成绩,恨不得把所有算法都啃了,结果大部分算法最后都没有吃透,只是学了个皮毛,真正遇到问题的时候,脑子没有转过弯来,就很难把算法和实际问题的关系 「 联系 」 起来。
原因还是因为学的时候 「 太过功利 」 ,只是为了眼前的成败得失,而 「 忽略了更加重要的东西 」 。
更加重要的东西并不是这个算法本身,而是设计算法的 「 思维 」 以及 「 思考的过程 」 ,算法是死的,思维是活的!学习的时候多加思考,对日后的发展有 「 百利而无一害 」 。
一、概念定义
1、闰年定义
闰年 和 平年 是两个相对的概念,简单而言,平年为 365 天,而闰年则有 366 天。
闰年是为了弥补因人为历法规定造成的年度天数与地球 「 实际公转周期 」 的时间差而设立的。补上时间差的年份为闰年。
而这多出来的一天就是 「 2月29日 」。
2、闰年计算
由于一个回归年为365天5小时48分45.5秒。所以:
1)普通年份能被
整除,且不能被
整除的是闰年。
2)世纪年份能被
整除的是闰年。
3)对于数值很大的年份,这年如果能被3200整除,并且还能被172800整除的才是闰年,这种情况,一般题目也遇不到,可以不做记忆。
3、闰年程序实现
所以,在遇到实际问题的时候,我们可以用以下函数来判断一个年份是否是闰年。
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100) || (year % 400 == 0);
}
二、题目描述
给定一个按
YYYY-MM-DD
格式表示日期的字符串date
,请计算并返回该日期是当年的第几天。
三、算法详解
如果这个月是
,那么只要统计
到
个月每个月的天数总和,再加上这个月的当前天数就是答案了。
这个问题涉及到一些字符串操作,例如:字符串转整型、取字符串的子串 等操作。
四、源码剖析
bool isLeapYear(int y) {
return (y % 4 == 0 && y % 100 || y % 400 == 0);
}
int strToInt(char *str, int len) {
int i, sum = 0;
for(i = 0; i < len; ++i) {
sum = sum * 10 + (str[i] - '0');
}
return sum;
}
int dayOfYear(char * date){
int monthday[] = { 0, // (1)
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
int sumday[13], i;
int year, month, day;
year = strToInt(date + 0, 4); // (2)
month = strToInt(date + 5, 2); // (3)
day = strToInt(date + 8, 2); // (4)
monthday[2] = isLeapYear(year) ? 29 : 28; // (5)
sumday[0] = 0;
for (i = 1; i < month; ++i) { // (6)
sumday[i] = sumday[i - 1] + monthday[i];
}
return sumday[month - 1] + day; // (7)
}
-
monthday[i]
存储了第 个月有多少天; - 取字符串 的字符作为年;
- 取字符串 的字符作为月;
- 取字符串 的字符作为日;
- 根据闰年还是平年重新填充二月的天数;
- 计算前面所有月份的天数累加值;
- 前面所有月份的天数 + 当前月份的天数 就是所求;
五、推荐专栏
六、习题练习
- 点赞
- 收藏
- 关注作者
评论(0)