先尝试1的解题方案,要么是先完成陆地设施,然后是水上设施,要么是先完成水上设施然后是陆地设施,
因此对于每种方案,只要找到第二个完成的最早开始时间,即max(第一个设施结束时间,第二个设施开始时间),然后加上第二个项目的持续时间,这样就合理了。
java
class Solution {
public int earliestFinishTime(int[] landStartTime, int[] landDuration, int[] waterStartTime, int[] waterDuration) {
int n = landStartTime.length;
int m = waterStartTime.length;
int minTime = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
// 获取当前陆地时间
int landStart = landStartTime[i];
int landEnd = landStart + landDuration[i];
// 遍历水上时间
for (int j = 0; j < m; j++) {
// 获取水上时间
int waterStart = waterStartTime[j];
int waterEnd = waterDuration[j] + waterStart;
// 假设是先陆地后水上
// 获取水上的最晚开始时间,也就是等陆地完成
int actualWaterStart = Math.max(landEnd, waterStart);
int totalTime1 = actualWaterStart + waterDuration[j];
// 先水上后陆地,也就是等水上完成
int actualLandStart = Math.max(waterEnd, landStart);
int totalTime2 = actualLandStart + landDuration[i];
minTime = Math.min(minTime, Math.min(totalTime1, totalTime2));
}
}
return minTime;
}
}
显然是暴力枚举讨论的,双重循环,在当前数据量的情况下会超时,
找到优化的地方,既然这个时间是max(第一个设施结束时间,第二个设施开始时间),可以发现表达式随着第一个设施结束时间是增大单调不减的,
所以为了使最终完成时间最小,只需要保留第一类项目中的最早结束时间即可。
同理另外一个先水上后陆地也是一样的道理。
所以先找到陆地结束时间最小,再计算水上结束时间最小,即可
反过来,计算水上结束时间最小,再计算陆地结束时间最小,
java
class Solution {
public int earliestFinishTime(int[] landStartTime, int[] landDuration, int[] waterStartTime, int[] waterDuration) {
// 公共方法,
int time1 = solve(landStartTime, landDuration, waterStartTime, waterDuration);
int time2 = solve(waterStartTime, waterDuration, landStartTime, landDuration);
return Math.min(time1, time2);
}
private int solve(int[] start1, int[] duration1, int[] start2, int[] duration2) {
// 先找出第一个最早结束时间
int finish1 = Integer.MAX_VALUE;
for (int i = 0; i < start1.length; i++) {
finish1 = Math.min(finish1, start1[i] + duration1[i]);
}
// 第二个的最早结束时间
int finish2 = Integer.MAX_VALUE;
for (int j = 0; j < start2.length; j++) {
finish2 = Math.min(finish2, Math.max(start2[j], finish1) + duration2[j]);
}
return finish2;
}
}
这样就从O(nm)优化到O(n + m),线性复杂度。