top1编程
← 返回题目
题解

输出日期差

1 条题解

  • 0
    @ 2026-8-5 10:24:13

    解题思路

    要算两个日期相差多少天,我们可以先定一个"起点",比如公元 1 年 1 月 1 日。然后写一个函数,把任意日期都换算成"从起点到这一天一共有多少天"。这样两个日期都换成天数后,相减就是它们相差的天数。

    题目还特别说明:计算差值时包括第二个日期那一天,不包括第一个日期那一天。这正好等于 days(第二个日期) - days(第一个日期),因为 days 数的是"到这一天为止一共多少天",相减时第二天的当天被算进去了,第一天的当天被减掉了。

    换算天数的时候,最麻烦的是闰年。闰年的判断规则是:

    • 能被 4 整除,但不能被 100 整除;
    • 或者能被 400 整除。

    闰年的 2 月有 29 天,比平年多 1 天。

    函数 days(y, m, d) 这样做:

    1. 先把 y 之前的每一年都加上天数:平年加 365,闰年加 366;
    2. 再把今年已经过去的月份的天数加起来(2 月要看是不是闰年);
    3. 最后加上当月已经过去的天数 d。

    题目要求用 scanf 和 printf 来输入输出,年份按 YYYY-MM-DD 格式读入。

    参考代码

    // P4514 输出日期差:计算两个日期相差的天数(含结束日,不含开始日)
    #include <cstdio>
    using namespace std;
    
    // 判断y年是否为闰年
    bool isLeap(int y) {
        return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
    }
    
    // 返回从公元1年1月1日到y年m月d日一共经过的天数
    int days(int y, int m, int d) {
        int mon[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int sum = 0;
        for (int i = 1; i < y; i++) {   // 累加整年的天数(闰年多1天)
            sum += 365 + isLeap(i);
        }
        for (int i = 1; i < m; i++) {   // 累加本年已过月份的天数
            sum += mon[i];
        }
        if (m > 2 && isLeap(y)) sum++;  // 闰年且已经过了2月,再加1天
        sum += d;                       // 加上当月已经过的天数
        return sum;
    }
    
    int main() {
        int y1, m1, d1, y2, m2, d2;
        scanf("%d-%d-%d %d-%d-%d", &y1, &m1, &d1, &y2, &m2, &d2);
        // 差值 = 后一天数 - 前一天数(含后一天、不含前一天,正好等于天数差)
        printf("%d
    ", days(y2, m2, d2) - days(y1, m1, d1));
        return 0;
    }
    

    复杂度分析

    每个日期都要循环一遍,把年份和月份都加一遍。年份最多是四位数,所以每次调用大约要算几千次,时间复杂度是 O(年份数),非常快。只用了几个变量和一个大小固定的月份表,空间复杂度是 O(1)。

    • 1