日期:2026年6月3日
LeetCode 題目連結:3635. Earliest Finish Time for Land and Water Rides II
解題想法
3633. Earliest Finish Time for Land and Water Rides I 的加強版,由於測資數量大很多,不能用簡單版的寫法,速度太慢。
Python 程式碼
Runtime: 778 ms, beats 7.27%. Memory: 39.98 MB, beats 12.73%.
from bisect import bisect_right
class Solution:
def earliestFinishTime(self, landStartTime: List[int], landDuration: List[int], waterStartTime: List[int], waterDuration: List[int]) -> int:
n, m = len(landStartTime), len(waterStartTime)
# 合併開始、經過時刻,組成 (開始時刻, 經過時間)
land = list(zip(landStartTime, landDuration))
water = list(zip(waterStartTime, waterDuration))
land.sort() # 依照開始時刻排序
water.sort()
# 取出排序後的開始時刻,用於二分搜尋法
landStart = [s for s, _ in land]
waterStart = [s for s, _ in water]
# 前綴最短持續時間
landDurationMin = [0] * n
landDurationMin[0] = land[0][1]
for i in range(1, n):
landDurationMin[i] = min(landDurationMin[i-1], land[i][1])
waterDurationMin = [0] * m
waterDurationMin[0] = water[0][1]
for i in range(1, m):
waterDurationMin[i] = min(waterDurationMin[i-1], water[i][1])
# 後綴最早結束時刻
landFinishMin = [0] * n
landFinishMin[-1] = land[-1][0] + land[-1][1]
for i in range(n-2, -1, -1):
landFinishMin[i] = min(landFinishMin[i+1], land[i][0] + land[i][1])
waterFinishMin = [0] * m
waterFinishMin[-1] = water[-1][0] + water[-1][1]
for i in range(m-2, -1, -1):
waterFinishMin[i] = min(waterFinishMin[i+1], water[i][0] + water[i][1])
# 先去 land 再去 water 的最早結束時刻
ans = float('inf') # 答案
for landS, landD in land:
landF = landS + landD # 結束時刻
# 用二分搜尋法從 waterStart 之中找分界點 idx
# idx 左側,已開放,可以直接玩
# idx 右側,尚未開放,要等一段時間
idx = bisect_right(waterStart, landF)
currMin = float('inf') # 目前的最短時間
# 狀況1,可以直接玩已開放的設施,取 landF 加上 0 ~ idx-1 最短持續時間
if idx > 0:
currMin = min(currMin, landF + waterDurationMin[idx - 1])
# 狀況2,等待還沒有開放的設施,取 idx ~ m-1 最早結束時刻
if idx < m:
currMin = min(currMin, waterFinishMin[idx])
# 更新 ans
ans = min(ans, currMin)
# 先去 water 再去 land 的最早結束時刻
for waterS, waterD in water:
waterF = waterS + waterD # 結束時刻
# 用二分搜尋法從 landStart 之中找分界點 idx
# idx 左側,已開放,可以直接玩
# idx 右側,尚未開放,要等一段時間
idx = bisect_right(landStart, waterF)
currMin = float('inf') # 目前的最短時間
# 狀況1,可以直接玩已開放的設施,取 waterF 加上 0 ~ idx-1 最短持續時間
if idx > 0:
currMin = min(currMin, waterF + landDurationMin[idx - 1])
# 狀況2,等待還沒有開放的設施,取 idx ~ n-1 最早結束時刻
if idx < n:
currMin = min(currMin, landFinishMin[idx])
# 更新 ans
ans = min(ans, currMin)
# 回傳答案
return ans