LeetCode 每日一题笔记
0. 前言
- 日期:2026.06.02
- 题目:3633. 最早完成陆地和水上游乐设施的时间 I
- 难度:简单
- 标签:数组、贪心
1. 题目理解
问题描述 :
必须恰好选1个陆地项目、1个水上项目,游玩顺序二选一:先陆地后水上 / 先水上后陆地;项目最早只能在自身startTime开启,结束后立刻开启下一个项目,下一个项目若还没到开启时间就等待到开启,求全部游玩完毕的最小结束时间。
示例:
输入:landStartTime=1,4,landDuration=3,2,waterStartTime=3,5,waterDuration=2,1
输出:6
2. 解题思路
核心观察
- 单个项目单独游玩的结束时间 = start + duration;
- 只有两种游玩顺序,最优解一定出自「陆地最优单品搭配水上最优单品」;
- 顺序1:先陆地→水上:陆地结束时间A,水上开始=max(水上start,A),总结束=开始+水上时长;
- 顺序2:先水上→陆地:水上结束时间B,陆地开始=max(陆地start,B),总结束=开始+陆地时长;
- 两种顺序结果取最小即为答案。
算法步骤
- 遍历陆地数组,求出单独游玩结束最早的陆地minLandEnd;
- 用minLandEnd逐个搭配所有水上项目,算出先陆后水的全局最优min1;
- 遍历水上数组,求出单独游玩结束最早的水上minWaterEnd;
- 用minWaterEnd逐个搭配所有陆地项目,算出先水后陆的全局最优min2;
- return min(min1,min2)。
3. 代码实现
java
package lc3600_lc3699.lc3633;
class Solution {
public int earliestFinishTime(int[] landStartTime, int[] landDuration, int[] waterStartTime, int[] waterDuration) {
int res = Integer.MAX_VALUE;
for (int i = 0; i < landStartTime.length; i++) {
int ls = landStartTime[i];
int ld = landDuration[i];
for (int j = 0; j < waterStartTime.length; j++) {
int ws = waterStartTime[j];
int wd = waterDuration[j];
int end1 = Math.max(ls, 0) + ld;
end1 = Math.max(ws, end1) + wd;
int end2 = Math.max(ws, 0) + wd;
end2 = Math.max(ls, end2) + ld;
res = Math.min(res, Math.min(end1, end2));
}
}
return res;
}
}
4. 代码优化说明
(原优化代码保留不变,附加行注释)
java
class Solution {
public int earliestFinishTime(int[] landStartTime, int[] landDuration, int[] waterStartTime, int[] waterDuration) {
int n = landStartTime.length;
int minEnd = Integer.MAX_VALUE;
// 遍历陆地,筛选单独游玩结束时间最小的陆地项目
for(int i=0;i<n;i++){
if(landStartTime[i]+landDuration[i]<minEnd){
minEnd = landStartTime[i]+landDuration[i];
}
}
int minEnd2 = Integer.MAX_VALUE;
// 用最优陆地搭配所有水上,求【先陆地后水上】最小结束时间
for(int i=0;i<waterStartTime.length;i++){
int s = Math.max(minEnd,waterStartTime[i]);
if(s+waterDuration[i]<minEnd2){
minEnd2 = s+waterDuration[i];
}
}
int minEnd3 = Integer.MAX_VALUE;
// 遍历水上,筛选单独游玩结束时间最小的水上项目
for(int i=0;i<waterStartTime.length;i++){
if(waterStartTime[i]+waterDuration[i]<minEnd3){
minEnd3 = waterStartTime[i]+waterDuration[i];
}
}
int minEnd4 = Integer.MAX_VALUE;
// 用最优水上搭配所有陆地,求【先水上后陆地】最小结束时间
for(int i=0;i<n;i++){
int s = Math.max(minEnd3,landStartTime[i]);
if(s+landDuration[i]<minEnd4){
minEnd4 = s+landDuration[i];
}
}
// 两种游玩方案取最小值
return Math.min(minEnd2,minEnd4);
}
}
5. 复杂度分析
- 暴力双重循环:时间O(N⋅M)O(N \cdot M)O(N⋅M),空间O(1)O(1)O(1)
- 贪心优化版:时间O(N+M)O(N+M)O(N+M),空间O(1)O(1)O(1)
6. 总结
- 贪心关键点:全局最优一定是单品最优互相组合,不用全量枚举所有配对;
- 只分先后两种游玩次序,分别计算最优再对比即可;
- 优化把平方复杂度降为线性,大数据下效率提升明显。