> 文章列表 > 【LeetCode】2409. 统计共同度过的日子数

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

【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;}
}