【算法】日期问题(C/C++)

server/2024/11/20 7:03:24/

目录

日期问题概述

一、闰年判断

问题描述:

解决方法:

代码实现:

二、回文日期

问题描述:

链接:2867. 回文日期 - AcWing题库

解决方法:

代码实现:

三、日期差值

问题描述:

链接:3498. 日期差值 - AcWing题库

解决方法:

代码实现:

四、日期格式化输入输出

问题描述:

解决方法:

代码实现:


日期问题算法初学时,可所谓屡见不鲜。因为算法初学者在写算法入门题时,会发现做的最多的题就是模拟题,那么模拟题最喜欢的出的就是日期问题日期问题分为好几个具体的问题,比如:闰年判断、回文日期日期差值等。本篇博客会带领大家详细讲解日期问题

日期问题概述

日期问题见名知意,就是有关时间的问题,出题人在时间这一个角度去做文章,现在来看各大刷题网站,什么样的时间问题都有,比如闰年判断、回文日期日期差值、日期格式化输入输出、时间轮询、时间窗口问题等。可所谓眼花缭乱,但是有的时间问题感觉就是图一乐,但是不排除创新题的可能性,后续也没有什么作用,既不会考也不会出在面试题上,下面我会对几种常见的日期问题进行详解。


一、闰年判断

问题描述:

一般题目会给你一个年份,或者让你输入一个年份,让你去判断这个年份是不是闰年。

解决方法:

闰年判断,只要牢记这一句话就可以,能够被4整除并且不能被100整除或者能够被400整除。就是只要满足下面任意一个条件就可以。

1.年份能够被4整除但是不能被100整除        --> year%4==0&&year%100!=0                      

2.年份能够被400整除                                   --> year%400==0

代码实现:

#include<stdio.h>int main(){int year;scanf("%d",&year);if(year%4==0&&year%100!=0||year%400==0){//条件printf("%d is a leap year\n",year);}else{printf("%d is not a leap year\n",year);}return 0;
}

二、回文日期

问题描述:

回文日期就是我们C语言课上经常说的回文数,类似于123321、12321等这样对称的数,那么在日期问题上,可以做很多扩展。这种问题看上去很简单,但是属于大模拟问题,写的代码比较长,因为我们既要根据月份不同给增加的天数不同,2月份天数还要根据闰年定。下面我们以acwing上的一道题为例子进行讲解回文日期问题

链接:2867. 回文日期 - AcWing题库

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。

因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。

我们称这样的日期是回文日期

有人表示 20200202 是“千年一遇” 的特殊日子。

对此小明很不认同,因为不到 22 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。

也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期

对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 21212121 年 12 月 12 日。

算不上“千年一遇”,顶多算“千年两遇”。

给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

注意: 本题数据保证一定有解。

注意

下一个回文日期和下一个 ABABBABA 型的回文日期可能是同一天。

ABABBABA 型的回文日期,需要满足 A≠B。

输入格式

输入包含一个八位整数 N,表示日期。

输出格式

输出两行,每行 1 个八位数。

第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期

数据范围

对于所有评测用例,10000101≤N≤89991231,保证 N 是一个合法日期的 88 位数表示。

输入样例:

20200202

输出样例:

20211202
21211212

解决方法:

题目要求我们寻找下一个回文日期跟ABABBABA 型的回文日期,那么我们就要在一次搜索中同时判断此两个回文日期

我们一般会根据天数设置一个月份的天数的数组(2月份28天),那么涉及到2月份就要判断闰年,我们再写一个函数去判断闰年。我们根据输入的日期每一次去递增1去寻找回文日期。当两个符合条件的日期循环才可以停,当递增1时,可能引起天数、月份的进位,那么我们要去写一个获取天数的函数,当天数大于此月份的天数,那么月份+1,月份越界了,年份+1。

代码实现:

#include<iostream>
using namespace std;
bool found1=false,found2=false;//found1为下一个回文日期判断是否找到,found2ABABBABA 型的回文日期
int months[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//月份天数数组
int is_leap(int year){//判断是否为闰年if(year%4==0&&year%100||year%400==0){return 1;}return 0;
}
int get_day(int year,int month){//获取天数if(month==2){return 28+is_leap(year);}return months[month];
}
void next_day(int &y,int &m,int &d){//自增到下一天d++;if(d>get_day(y,m)){d=1;m++;if(m>12){m=1;y++;}}
}
bool cheak1(char s[]){//判断日期是否为回文日期for(int i=0,j=7;i<j;i++,j--){if(s[i]!=s[j]){return false;}}return true;
}
bool cheak2(char s[]){//判断是否为ABABBABA 型的回文日期char a=s[0];char b=s[1];char c=s[2];char d=s[3];if(a==c&&b==d&&a!=b){return true;}return false;
}
int main(){int y,m,d;char s[10];//中介作用,负责转化scanf("%04d%02d%02d",&y,&m,&d);while(!found1||!found2){next_day(y,m,d);sprintf(s,"%04d%02d%02d",y,m,d);if(cheak1(s)){if(!found1){found1=true;puts(s);}if(!found2&&cheak2(s)){found2=true;puts(s);}}}return 0;
}

三、日期差值

问题描述:

日期差值,顾名思义,给定两个日期,让我们计算这两个日期之前有多少天。那么这种问题看上去很简单,但是也是属于大模拟问题,因为,我们要考虑12个月份天数的不同,当需要借位时,我们还要根据上一个月不同的天数给增加多少天,下面我们以acwing上的一道题为例题,进行讲解。

链接:3498. 日期差值 - AcWing题库

有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。

输入格式

输入包含多组测试数据。

每组数据占两行,分别表示两个日期,形式为 YYYYMMDD。

输出格式

每组数据输出一行,即日期差值

数据范围

年份范围 [1,9999]
保证输入日期合法。
测试数据的组数不超过 100

输入样例:

20110412
20110422

输出样例:

11

解决方法:

求两个日期之前的差值,模拟的做法就是y2-y1,m2-m1,d2-d1,思路是这样的,但是这样需要考虑借位、闰年等,比较麻烦,那么我们可以转变思路求出第一年1月1日起到y1年m1月d1日共多少天为t1天,第一年1月1日起到y2年m2月d2日共多少天,为t2天,|t2-t1|+1即为答案。求多少天时,要先求y1-1年,m-1月,共多少天,再加上d1即可。上代码。

代码实现:

#include<iostream>
using namespace std;
int months[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//一年365天月份数组
int is_leap(int year){//判断是否为闰年if(year%4==0&&year%100||year%400==0){return 1;}else{return 0;}
}
int getday(int year,int month){//获取哪一年哪一月的天数if(month==2)return 28+is_leap(year);//判断闰年二月份29天return months[month];
}
int calc(int year,int month,int day){//1~year年month月day日共多少天int ans=0;for(int i=1;i<year;i++){ans+=365+is_leap(i);//闰年多一天}for(int i=1;i<month;i++){ans+=getday(year,i);}return ans+day;
}
int main(){int y1,m1,d1,y2,m2,d2;while(~scanf("%04d%02d%02d\n%04d%02d%02d",&y1,&m1,&d1,&y2,&m2,&d2)){//多组输入//%04d表示输入为4位,不足4位前面补0printf("%d\n",abs(calc(y1,m1,d1)-calc(y2,m2,d2))+1);//两个日期之差取绝对值//+1,自己也是一天,比如1月1到1月2,这是两天,相减是一天,所以要加1}return 0;
}

四、日期格式化输入输出

问题描述:

当我们需要输入输出日期时,必须按照题目所给的格式进行输入输出,比如yyyy年mm月dd日,当年份只有三位时前面需要补0,比如0202年,月份为个位数月份时,前一位需要补0,例如01、03月,日期同理。

解决方法:

我们根据上面,可以发现规律,知道了输入输出的规律,年份为四位,不够前面补0;月份为2位,不够前面补0;天数为2位,不够前面补0。

要实现上面的规律我们就要在输入输出函数上做一下手脚。在c语言输出输出时%yd,在y处填入数字num,它会自动格式化为num位,那么%xyd,在x处填入数字tep,在y处填入数字num,它意味着输入输出的数字自动格式化为num位,如果不足num位前面补tep这个数。

代码实现:

scanf("%04d%02d%02d\n%04d%02d%02d",&y1,&m1,&d1,&y2,&m2,&d2)//输入,不足的补0printf("%04d%02d%02d",y,m,d);//输出方法一,不足的补0
sprintf(s,"%04d%02d%02d",y,m,d);//输出方法二,先把ymd转化为格式化的字符串,再输出
puts(s);

日期问题在模拟题中还是比较多的,在算法竞赛中,像icpc、ccpc这种竞赛比较少,日期问题能创新的基本都创新了,没有什么新题可以出了。但是在蓝桥杯中,日期问题是热点问题,基本每一年都要考,参加蓝桥杯的同学还是很有必要好好学一下日期问题。本篇博客中涉及到的日期问题只解释了四个,还有很多日期问题没有写,希望大家在以后刷题中自己总结,这里不再过多解释。

执笔至此,感触彼多,全文将至,落笔为终,感谢大家的支持。


http://www.ppmy.cn/server/143410.html

相关文章

ISUP协议视频平台EasyCVR私有化部署视频平台如何实现RTMP推流将大疆无人机的视频画面回传?

在现代视频监控和流媒体技术领域&#xff0c;EasyCVR视频融合云平台以其卓越的性能和灵活性&#xff0c;成为了跨区域、网络化视频监控综合管理的理想选择。作为TSINGSEE青犀视频“云边端”架构体系中的核心组件&#xff0c;私有化部署视频平台EasyCVR不仅能够实现视频数据的集…

PWN:手动编写 x64 基于syscall 的 shell code(TODO)

syscall 在AMD64架构&#xff08;也称为x86-64或x64&#xff09;下&#xff0c;使用 syscall 指令来进行系统调用的约定如下&#xff1a; 系统调用号&#xff1a;存储在 RAX 寄存器中。参数传递&#xff1a; 第一个参数&#xff1a;RDI第二个参数&#xff1a;RSI第三个参数&a…

Vue3 虚拟列表组件库 virtual-list-vue3 的使用

Vue3 虚拟列表组件库 virtual-list-vue3 的基本使用 分享个人写的一个基于 Vue3 的虚拟列表组件库&#xff0c;欢迎各位来进行使用与给予一些更好的建议&#x1f60a; 概述&#xff1a;该组件组件库用于提供虚拟化列表能力的组件&#xff0c;用于解决展示大量数据渲染时首屏渲…

synchronized和volatile区别

synchronized和volatile都是Java中用于实现多线程同步的机制&#xff0c;但它们之间存在显著的差异。以下是对两者的详细比较&#xff1a; 一、作用机制 synchronized 锁机制&#xff1a;synchronized利用锁来保证同步。当某个线程进入由synchronized修饰的方法或代码块时&…

SwiftUI 高级开发教程 - 第一章:深入理解 SwiftUI 的声明式编程

一、声明式编程的核心概念与优劣势 1.1 什么是声明式编程? 声明式编程是一种以描述“是什么”为核心思想的编程范式。它与命令式编程的最大区别在于,开发者只需要告诉程序“我想要什么样的结果”,而不需要告诉它“如何一步步实现结果”。这一特性在构建复杂 UI 时尤其有用…

蓝桥杯某例题的解决方案和拓展(完全能解决例题本身)

蓝桥杯题目&#xff1a;求1&#xff08;包含&#xff09;直到20230408&#xff08;包含&#xff09;所有自然数的加和。 这个题比较恶心的一点在于&#xff0c;20230408本身没有超过int的上限&#xff0c;但是它的加和是超过int上限的&#xff0c;因此如果直接用int来计算&…

11.9.2024刷华为

文章目录 HJ31 单词倒排HJ32 密码提取语法知识记录 傻逼OD题目又不全又要收费&#xff0c;看毛线&#xff0c;莫名奇妙 HW这叼机构别搁这儿害人得不得&#xff1f; 我觉得我刷完原来的题目 过一遍华为机考的ED卷出处&#xff0c;就行了 HJ31 单词倒排 游戏本做过了好像 HJ3…

聚焦 AUTO TECH 2025华南展:探索新能源汽车发展新趋势

随着“新四化”浪潮的推进&#xff0c;汽车行业正经历前所未有的变革。中国新能源汽车正逐渐走向世界。国内汽车制造巨头如比亚迪、吉利、奇瑞、长安等&#xff0c;已经将出口提升至核心战略地位。中国新能源汽车的发展&#xff0c;不仅推动了全球汽车产业的电动化转型&#xf…