《算法零基础100讲》(第6讲) 日期算法

举报
英雄哪里出来 发表于 2021/10/29 12:42:38 2021/10/29
【摘要】 让天下没有难学的算法

零、写在前面

  这是《算法零基础100讲》 专栏打卡学习的第六天了,学习算法的时候, 「 切忌心浮气躁 」 ,就像十年前的我,为了竞赛取得成绩,恨不得把所有算法都啃了,结果大部分算法最后都没有吃透,只是学了个皮毛,真正遇到问题的时候,脑子没有转过弯来,就很难把算法和实际问题的关系 「 联系 」 起来。
  原因还是因为学的时候 「 太过功利 」 ,只是为了眼前的成败得失,而 「 忽略了更加重要的东西 」
  更加重要的东西并不是这个算法本身,而是设计算法的 「 思维 」 以及 「 思考的过程 」 ,算法是死的,思维是活的!学习的时候多加思考,对日后的发展有 「 百利而无一害 」

一、概念定义

1、闰年定义

  闰年 和 平年 是两个相对的概念,简单而言,平年为 365 天,而闰年则有 366 天。
  闰年是为了弥补因人为历法规定造成的年度天数与地球 「 实际公转周期 」 的时间差而设立的。补上时间差的年份为闰年。
  而这多出来的一天就是 「 2月29日 」

2、闰年计算

  由于一个回归年为365天5小时48分45.5秒。所以:
    1)普通年份能被 4 4 整除,且不能被 100 100 整除的是闰年。
    2)世纪年份能被 400 400 整除的是闰年。
    3)对于数值很大的年份,这年如果能被3200整除,并且还能被172800整除的才是闰年,这种情况,一般题目也遇不到,可以不做记忆。

3、闰年程序实现

  所以,在遇到实际问题的时候,我们可以用以下函数来判断一个年份是否是闰年。

bool isLeapYear(int year) {
	return (year % 4 == 0 && year % 100) || (year % 400 == 0);
}

二、题目描述

  给定一个按YYYY-MM-DD格式表示日期的字符串date,请计算并返回该日期是当年的第几天。

三、算法详解

  如果这个月是 m m ,那么只要统计 1 1 m 1 m-1 个月每个月的天数总和,再加上这个月的当前天数就是答案了。
  这个问题涉及到一些字符串操作,例如:字符串转整型、取字符串的子串 等操作。

四、源码剖析

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)
}
  • ( 1 ) (1) monthday[i]存储了第 i i 个月有多少天;
  • ( 2 ) (2) 取字符串 [ 0 3 ] [0- 3] 的字符作为年;
  • ( 3 ) (3) 取字符串 [ 5 6 ] [5-6] 的字符作为月;
  • ( 4 ) (4) 取字符串 [ 8 9 ] [8-9] 的字符作为日;
  • ( 5 ) (5) 根据闰年还是平年重新填充二月的天数;
  • ( 6 ) (6) 计算前面所有月份的天数累加值;
  • ( 7 ) (7) 前面所有月份的天数 + 当前月份的天数 就是所求;

五、推荐专栏

🧡《C语言入门100例》🧡

闰年 和 平年

六、习题练习

请参考原文

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。