【LeetCode】2409. 统计共同度过的日子数

1. 问题

Alice 和 Bob 计划分别去罗马开会。

给你四个字符串 arriveAlice ,leaveAlice ,arriveBob 和 leaveBob 。Alice 会在日期 arriveAlice 到 leaveAlice 之间在城市里(日期为闭区间),而 Bob 在日期 arriveBob 到 leaveBob 之间在城市里(日期为闭区间)。每个字符串都包含 5 个字符,格式为 "MM-DD" ,对应着一个日期的月和日。

请你返回 Alice和 Bob 同时在罗马的天数。

你可以假设所有日期都在 同一个 自然年,而且 不是 闰年。每个月份的天数分别为:[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 。

示例 1:
输入:arriveAlice = "08-15", leaveAlice = "08-18", arriveBob = "08-16", leaveBob = "08-19"
输出:3
解释:Alice 从 8 月 15 号到 8 月 18 号在罗马。Bob 从 8 月 16 号到 8 月 19 号在罗马,他们同时在罗马的日期为 8 月 16、17 和 18 号。所以答案为 3 。

示例 2:
输入:arriveAlice = "10-01", leaveAlice = "10-31", arriveBob = "11-01", leaveBob = "12-31"
输出:0
解释:Alice 和 Bob 没有同时在罗马的日子,所以我们返回 0 。

提示:
所有日期的格式均为 “MM-DD”
Alice 和 Bob 的到达日期都 早于或等于 他们的离开日期。
题目测试用例所给出的日期均为 非闰年 的有效日期。

2. 解题思路

类似数学上,求两集合的交集,或者两区间,求交集。假如两集合[A,B], [C,D],如果求交集,有以下几种情况需要讨论:
1)若B<C, 或者 D<A,则两区间根本不相交,无交集;
2)若B>=C 且 B<=D,则交集为[C,B];
3)若D>=A 且 D<=B,则交集为[A,D];

对于题目中的已知条件,对于字符串做大小比较,需要用到 String.compareTo,很容易写成<,>,面试时容易掉到坑里。

1)中的情况,写成代码如下:

//1.Alice离开日期 小于 Bob到达日期
if(leaveAlice.compareTo(arriveBob)<0){
    return 0;
}
//2.Bob离开日期 小于 Alice到达日期
if(leaveBob.compareTo(arriveAlice)<0){
    return 0;
}

2)和3),我们需要确定边界,交集的左边界以Max(arriveAlice, arriveBob),右边界以Min(leaveAlice, leaveBob)

//左边界
String maxLeft=arriveAlice.compareTo(arriveBob)>=0?arriveAlice:arriveBob;

//右边界
String minRight=leaveAlice.compareTo(leaveBob)>=0?leaveBob:leaveAlice;

在计算日子数时,为方便调用对应月份的天数,定义一全局变量:

private static int[] days=new int[]{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

其中,days[0]=0.

对于MM-DD的拆分,以左边界为例:

String[] left=maxLeft.split("-");
int leftMonth=Integer.parseInt(left[0]);
int leftDay=Integer.parseInt(left[1]);

对于日子数的计算,如果交集的结果属于同一月份,则日子数为 rightDay-leftDay+1; 否则:

int sum=0;
for(int i=leftMonth;i<=rightMonth;i++){
    if(i==rightMonth){
        sum+=rightDay;
    } else {
        sum+=days[i];
    }
}

结果为 sum-leftDay+1, 因为左边界当月已经过去了 leftDay 这么多天数。

3. 代码

class Solution {
    private static int[] days=new int[]{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    public int countDaysTogether(String arriveAlice, String leaveAlice, String arriveBob, String leaveBob) {
        //得有交集
        //1.Alice离开日期 小于 Bob到达日期
        if(leaveAlice.compareTo(arriveBob)<0){
            return 0;
        }
        //2.Bob离开日期 小于 Alice到达日期
        if(leaveBob.compareTo(arriveAlice)<0){
            return 0;
        }
        String maxLeft=arriveAlice.compareTo(arriveBob)>=0?arriveAlice:arriveBob;
        String minRight=leaveAlice.compareTo(leaveBob)>=0?leaveBob:leaveAlice;
        String[] left=maxLeft.split("-");
        int leftMonth=Integer.parseInt(left[0]);
        int leftDay=Integer.parseInt(left[1]);

        String[] right=minRight.split("-");
        int rightMonth=Integer.parseInt(right[0]);
        int rightDay=Integer.parseInt(right[1]);

        if(leftMonth==rightMonth){
            return rightDay-leftDay+1;
        }
        int sum=0;
        for(int i=leftMonth;i<=rightMonth;i++){
            if(i==rightMonth){
                sum+=rightDay;
            } else {
                sum+=days[i];
            }
        }
        return sum-leftDay+1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值