博主的解法过于冗长,是一直对着不同的案例debug修改出来的,不建议学习。虽然提交成功了,但是自己最后都不知道写的是啥了哈哈哈。
package keepcoding.leetcode.leetcode2409;
/*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]*/
public class Result01 {
public static void main(String[] args) {
int days = countDaysTogether("08-12","08-26","08-26","10-25");
System.out.println(days);
}
/*
输入: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 。
*/
public static int countDaysTogether(String arriveAlice, String leaveAlice, String arriveBob, String leaveBob) {
String[] arriveAliceTimeArray = arriveAlice.split("-",2);
String[] leaveAliceTimeArray = leaveAlice.split("-",2);
String[] arriveBobTimeArray = arriveBob.split("-",2);
String[] leaveBobTimeArray = leaveBob.split("-",2);
int aliceArriveMonth = Integer.valueOf(arriveAliceTimeArray[0]);
int aliceLeaveMonth = Integer.valueOf(leaveAliceTimeArray[0]);
int aliceArriveDay = Integer.valueOf(arriveAliceTimeArray[1]);
int aliceLeaveDay = Integer.valueOf(leaveAliceTimeArray[1]);
int bobArriveMonth = Integer.valueOf(arriveBobTimeArray[0]);
int bobLeaveMonth = Integer.valueOf(leaveBobTimeArray[0]);
int bobArriveDay = Integer.valueOf(arriveBobTimeArray[1]);
int bobLeaveDay = Integer.valueOf(leaveBobTimeArray[1]);
if (aliceArriveDay==bobArriveDay && aliceArriveMonth==bobArriveMonth && aliceLeaveDay==bobLeaveDay && aliceLeaveMonth==bobLeaveMonth){
if (aliceArriveDay==1 && aliceLeaveMonth==12){
return 365;
}else if (aliceArriveDay==28 && aliceArriveMonth==2 && aliceLeaveMonth==3){
return 2;
}
}
//alice和bob同一个月到
if (aliceArriveMonth == bobArriveMonth) {
//同一个月走
if (aliceLeaveMonth==bobLeaveMonth){
if (aliceArriveDay > bobLeaveDay || bobArriveDay > aliceLeaveDay) {//alice/bob到的时候 bob/alice已经走了 共同度过的日子为0
return 0;
} else {
//alice先到
if (aliceArriveDay <= bobArriveDay) {
return aliceLeaveDay <= bobLeaveDay ? (aliceLeaveDay-bobArriveDay)+1 : (bobLeaveDay-bobArriveDay)+1;
//alice后到
} else {
return aliceLeaveDay <= bobLeaveDay ? (aliceLeaveDay-aliceArriveDay)+1 : (bobLeaveDay-aliceArriveDay)+1;
}
}
//alice走的月份小于bob 即alice先走
}else if (aliceLeaveMonth<bobLeaveMonth){
if (aliceLeaveDay==bobArriveDay){
return 1;
}else {
int sumDays = aliceLeaveDay;
for (int i = aliceArriveMonth+1; i < aliceLeaveMonth; i++) {
sumDays += getMonthDays(i);
}
sumDays += aliceArriveDay>=bobArriveDay ? getMonthDays(aliceArriveMonth)-aliceArriveDay : getMonthDays(bobArriveMonth)-bobArriveDay;
return sumDays+1;
}
//alice走的月份大于bob 即bob先走
}else {
int sumDays = 0;
if (bobArriveMonth==bobLeaveMonth){
sumDays += bobLeaveDay - bobArriveDay;
}else {
sumDays = bobLeaveDay;
for (int i = bobArriveMonth+1; i <bobLeaveMonth ; i++) {
sumDays += getMonthDays(i);
}
sumDays += aliceArriveDay>=bobArriveDay ? getMonthDays(aliceArriveMonth)-aliceArriveDay : getMonthDays(bobArriveMonth)-bobArriveDay;
}
return sumDays+1;
}
//alice月份先到
} else if (aliceArriveMonth < bobArriveMonth) {
if (aliceLeaveMonth < bobArriveMonth) {//alice在bob到之前就走了
return 0;
//alice 走 的那个月 bob 到
} else if (aliceLeaveMonth == bobArriveMonth) {
if(aliceLeaveDay<=bobLeaveDay){
return bobArriveDay < aliceLeaveDay ? (aliceLeaveDay-bobArriveDay)+1 : 0;
}else {
return bobArriveDay < aliceLeaveDay ? (bobLeaveDay-bobArriveDay)+1 : 0;
}
//alice在bob到的月份之后的月份才走
} else {
//bob走的月份小于alice
if (bobLeaveMonth < aliceLeaveMonth) {
int sumDays = getMonthDays(bobArriveMonth) - bobArriveDay;
for (int i = bobArriveMonth + 1; i < bobLeaveMonth; i++) {
sumDays += getMonthDays(i);
}
sumDays += bobLeaveDay;
return sumDays+1;
//bob走的月份大于alice
} else if (bobLeaveMonth > aliceLeaveMonth) {
int sumDays = getMonthDays(bobArriveMonth) - bobArriveDay;
for (int i = bobArriveMonth + 1; i < aliceLeaveMonth; i++) {
sumDays += getMonthDays(i);
}
sumDays += aliceLeaveDay;
return sumDays+1;
//bob跟alice一个月走
}else {
int sumDays = getMonthDays(bobArriveMonth) - bobArriveDay;
for (int i = bobArriveMonth + 1; i < aliceLeaveMonth; i++) {
sumDays += getMonthDays(i);
}
sumDays += Math.min(aliceLeaveDay,bobLeaveDay);
return sumDays+1;
}
}
//bob月份先到
} else {
if (bobLeaveMonth < aliceArriveMonth) {//bob在alice到之前就走了
return 0;
//bob 走 的那个月 alice 到
} else if (bobLeaveMonth == aliceArriveMonth) {
return aliceArriveDay < bobLeaveDay ? (bobLeaveDay-aliceArriveDay)+1 : 0;
//bob在alice到的月份之后的月份才走
} else {
//alice走的月份小于bob
if (aliceLeaveMonth < bobLeaveMonth) {
int sumDays = getMonthDays(aliceArriveMonth) - aliceArriveDay;
for (int i = aliceArriveMonth + 1; i < aliceLeaveMonth; i++) {
sumDays += getMonthDays(i);
}
sumDays += aliceLeaveDay;
return sumDays+1;
//alice走的月份大于bob
} else if (aliceLeaveMonth > bobLeaveMonth) {
int sumDays = getMonthDays(aliceArriveMonth) - aliceArriveDay;
for (int i = aliceArriveMonth + 1; i < bobLeaveMonth; i++) {
sumDays += getMonthDays(i);
}
sumDays += bobLeaveDay;
return sumDays+1;
//alice跟bob一个月走
}else {
int sumDays = getMonthDays(aliceArriveMonth) - aliceArriveDay;
for (int i = aliceArriveMonth + 1; i < aliceLeaveMonth; i++) {
sumDays += getMonthDays(i);
}
sumDays += Math.min(aliceLeaveDay,bobLeaveDay);
return sumDays+1;
}
}
}
}
//获取月份对应的天数
public static int getMonthDays(int i){
switch (i){
case 1: return 31;
case 2: return 28;
case 3: return 31;
case 4: return 30;
case 5: return 31;
case 6: return 30;
case 7: return 31;
case 8: return 31;
case 9: return 30;
case 10: return 31;
case 11: return 30;
case 12: return 31;
default: return 0;
}
}
}
官方解较为巧妙,大家可以学习:
package keepcoding.leetcode.leetcode2409;
/*
我们可以设计一个函数 calculateDayOfYear 来计算输入中的每个日子在一年中是第几天。
计算输入中的每个日子在一年中是第几天时,可以利用前缀和数组来降低每次计算的复杂度。
知道每个日子是一年中的第几天后,可以先通过比较算出两人到达日子的最大值,离开日子的最小值,然后利用减法计算重合的日子
*/
public class Result02 {
public static void main(String[] args) {
int days = countDaysTogether("10-01","11-01","11-01","12-31");
System.out.println(days);
}
public static int countDaysTogether(String arriveAlice, String leaveAlice, String arriveBob, String leaveBob) {
//将每个月份的天数存入数组
int[] datesOfMonths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//累加数组——计算每个月在这一年已经过了多少天
int[] prefixSum = new int[13];
for (int i = 0; i < 12; i++) {
//i+1 是因为要在数组1-12的位置上一一对应的存入月份累加的天数 eg.一月这一年过了31天 二月过了31+28 三月31+28+31 ...
prefixSum[i + 1] = prefixSum[i] + datesOfMonths[i];
}
//计算alice到的天数是一年的第几天
int arriveAliceDay = calculateDayOfYear(arriveAlice, prefixSum);
//计算alice走的天数是一年的第几天
int leaveAliceDay = calculateDayOfYear(leaveAlice, prefixSum);
//计算bob到的天数是一年的第几天
int arriveBobDay = calculateDayOfYear(arriveBob, prefixSum);
//计算bob走的天数是一年的第几天
int leaveBobDay = calculateDayOfYear(leaveBob, prefixSum);
//用Math.min(leaveAliceDay, leaveBobDay)计算谁先走的,Math.max(arriveAliceDay, arriveBobDay)计算谁后到的
//如果存在共处的时间,先走的-后到的即为共处的天数
//如果先走的-后到的 < 0 证明没有相遇共处的时间——return 0;
// +1 是因为 如果alice走的那天bob到 根据题意这也算共处了一天 eg .alice 10-01到 10-31走 bob 10-31到 11-3走 ;根据先走的-后到的计算=0,但是有共处的一天,所以+1
return Math.max(0, Math.min(leaveAliceDay, leaveBobDay) - Math.max(arriveAliceDay, arriveBobDay) + 1);
}
//计算是哪一天到的
public static int calculateDayOfYear(String day, int[] prefixSum) {
//String类的substring()方法 ——截取字符串 https://blog.csdn.net/Crezfikbd/article/details/119708978
int month = Integer.parseInt(day.substring(0, 2));
int date = Integer.parseInt(day.substring(3));
return prefixSum[month - 1] + date;//到的这个月的前一个月总共过了多少天 再加上这个月到的日期 即为这一年的第几天
}
}
知道思路后自己又手敲了一遍:
package keepcoding.leetcode.leetcode2409;
public class DoItAgain {
public static void main(String[] args) {
int days = countTogetherDays("10-01","11-01","11-01","12-31");
System.out.println(days);
}
//计算哪天到
public static int countTogetherDays(String aliceArrive,String aliceLeave,String bobArrive,String bobLeave){
int[] monthDays = {31,28,31,30,31,30,31,31,30,31,30,31};
int[] preMonthSum = new int[13];
for (int i = 0; i < monthDays.length; i++) {
preMonthSum[i+1] = preMonthSum[i] + monthDays[i];
}
//计算alice一年中的第几天到
int aComDay = countDay(aliceArrive,preMonthSum);
//计算alice一年中的第几天走
int aGoDay = countDay(aliceLeave,preMonthSum);
//计算bob一年中的第几天到
int bComDay = countDay(bobArrive,preMonthSum);
//计算bob一年中的第几天走
int bGoDay = countDay(bobLeave,preMonthSum);
if (bComDay>aGoDay || aComDay>bGoDay){
//没有相遇
return 0;
}else {
//先走的-后到的日期
return Math.min(aGoDay,bGoDay) - Math.max(aComDay,bComDay) + 1;
}
}
//计算各个时间点是这一年的第多少天
public static int countDay(String s,int[] preMonthSum){
//转化截取的字符串——得到到达的月份、日期
int month = Integer.parseInt(s.substring(0,2));
int day = Integer.parseInt(s.substring(3));
//根据累加的数组结合当月到达的日期 计算到达的天数
return preMonthSum[month-1]+day;
}
}