《算法笔记》3.4小节——入门模拟->日期处理

问题 A: 日期差值

题目

题目描述

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

输入

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

输出

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

样例输入

1
2
20130101
20130105

样例输出

1
5

题解

思路

几个注意事项:

  • 为了方便我们使用一个二维数组math[13][2]存放每月的天数比较方便,需要分平年(一维)与闰年(二维);

  • 第一个日期大于第二个日期需要交换;

  • 为了节省时间,可以先对年份进行判断

  • 计算日期的差值,需要注意的是要判断一下闰年。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>

using namespace std;

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

int main()
{
// 每个月份的天数,第一维为平年,第二维为闰年
int month[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}};

int t1, t2, y1, y2, m1, m2, d1, d2;

// 直接用int来表示输入的数据,8位,够用。
while (scanf("%d%d", &t1, &t2) != EOF)
{
int res = 0;
// 为了方便运算,使第二个永远大于第一个
if (t1 > t2)
{
swap(t1, t2);
}

y1 = t1 / 10000, m1 = t1 / 100 % 100, d1 = t1 % 100;
y2 = t2 / 10000, m2 = t2 / 100 % 100, d2 = t2 % 100;

// 为了快速,先计算年份,到 y2 - 1
while (y1 < y2 - 1)
{
if (isLeapYear(y1))
{
res += 366;
}
else
{
res += 365;
}
y1++;
}

// 从y2 - 1年开始,计算每一天,直到 t2 时间
while (y1 < y2 || m1 < m2 || d1 < d2)
{
d1++;
if (d1 == month[m1][isLeapYear(y1)] + 1)
{
d1 = 1;
m1++;
}
if (m1 == 13)
{
y1++;
m1 = 1;
}
res++;
}
// 需要注意输出需要 +1
printf("%d\n", res + 1);
}

system("pause");
return 0;
}

问题 B: Day of Week

问题 C: 打印日期

题目

题目描述

给出年分m和一年中的第n天,算出第n天是几月几号。

输入

输入包括两个整数y(1<=y<=3000),n(1<=n<=366)。

输出

可能有多组测试数据,对于每组数据,按 yyyy-mm-dd的格式将输入中对应的日期打印出来。

样例输入 Copy

1
2
3
4
2013 60
2012 300
2011 350
2000 211

样例输出 Copy

1
2
3
4
2013-03-01
2012-10-26
2011-12-16
2000-07-29

题解

思路

这题不是很复杂,具体来说就是:

  • 年份正常不需要变化,只有特殊情况:平年 366 天需要年数 +1,月份归 0 ;
  • 正常计算思路为:
    • 先找到最后一天所在的月:月份的天数累加,直到超过输入的值,然后需要退一步循环;
    • 输出,该天的值 = 输入的值 - 上一步累加的天数;此时需要控制格式输出%0xd

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>

using namespace std;

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

/*
1. 年份直接输出即可
2. 月份与日需要计算,日要根据闰年、平年计算
*/
int main()
{
// 每个月份的天数,第一维为平年,第二维为闰年
int dMonth[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}};

int year, day;
while (scanf("%d %d", &year, &day) != EOF)
{
// 找到最后一天所在的月;resTemp 用来计算遍历到目前的值
int resMonth = 1, resDay = 1, resTemp = 0, leapYear = isLeapYear(year), i = 1;
for (; resTemp < day; i++)
{
resTemp += dMonth[i][leapYear];
resMonth++;
}
// 月份减一,临时和减一个月
i--;
resTemp -= dMonth[i][leapYear];
resMonth--;
if (resMonth == 13)
{
resMonth = 1;
year++;
}
printf("%04d-%02d-%02d\n", year, resMonth, day - resTemp);
}

system("pause");
return 0;
}

问题D:日期类

题目

题目描述

编写一个日期类,要求按xxxx-xx-xx的格式输出日期,实现加一天的操作。

输入

输入第一行表示测试用例的个数 m,接下来 m 行每行有 3 个用空格隔开的整数,分别表示年月日。测试数据不会有闰年。

输出

输出 m 行。按xxxx-xx-xx的格式输出,表示输入日期的后一天的日期。

样例输入

1
2
3
2
1999 10 20
2001 1 31

样例输出

1
2
1999-10-21
2001-02-01

提示

注意个位数日期前面要有 0。

题解

思路

  • 第一行的输入变量count作为循环条件;
  • 判断当前天数是否是当前月的最后一天,如果是,则天数置为 1,月份加 1;否则天数加 1,此时需要判断平闰年;
  • 如果月份 + 1 之后变为 13,则月份置为 1,年份加 1。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>

using namespace std;

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

int main()
{
int count = 0;
// 每个月份的天数,第一维为平年,第二维为闰年
int dMonth[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}};
scanf("%d", &count);

for (int i = 0; i < count; i++)
{
int year, month, day, leapYear = isLeapYear(year);
scanf("%d %d %d", &year, &month, &day);
if (day == dMonth[month][leapYear])
{
month++;
day = 1;
}
else
{
day++;
}
if (month == 13)
{
year++;
month = 1;
}
printf("%04d-%02d-%02d\n", year, month, day);
}

system("pause");
return 0;
}

问题E:日期类加

题目

题目描述

设计一个程序能计算一个日期加上若干天后是什么日期。

输入

输入第一行表示样例个数 m,接下来m行每行四个整数分别表示年月日和累加的天数。

输出

输出 m 行,每行按 yyyy-mm-dd 的个数输出。

样例输入

1
2
1
2008 2 3 100

样例输出

1
2008-05-13

题解

思路

不要想什么套路,最简单的做法就是最好的,只要提交不爆时间,一直leap--就好。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>

using namespace std;

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

int main()
{
int count = 0;
// 每个月份的天数,第一维为平年,第二维为闰年
int dMonth[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}};
scanf("%d", &count);
for (int i = 0; i < count; i++)
{
int year, month, day, leap, tempRes = 0;
scanf("%d %d %d %d", &year, &month, &day, &leap);

while (leap--)
{
day++;
if (day > dMonth[month][isLeapYear(year)])
{
day = 1;
month++;
}
if (month > 12)
{
year++;
month = 1;
}
}
printf("%04d-%02d-%02d\n", year, month, day);
}

system("pause");
return 0;
}

《算法笔记》3.4小节——入门模拟->日期处理
https://excelius.xyz/《算法笔记》3-4小节——入门模拟-日期处理/
作者
Ther
发布于
2021年11月19日
许可协议