力扣中國 · #42
接雨水(Trapping Rain Water)
使用雙指針從兩端向中間掃描,透過比較兩端高度決定當前處理邊界,並利用已掃描區域的最大值計算該位置積水量,避免額外空間開銷。
開啟原題 ↗時間複雜度O(n)
空間複雜度O(1)
解釋模型qwen/qwen3.8-27b
解題思路
本解法採用雙指針(Two Pointers)策略,從陣列兩端向中間收攏,以 O(1) 空間計算接水量。
核心邏輯基於「木桶效應」:每個位置能積蓄的雨水量,取決於其左側最大高度與右側最大高度中的較小值,再減去該位置本身的高度。然而,直接預計算左右最大值會消耗 O(n) 空間。此演算法透過維護兩個變數 lmx(左指針左側含自身遇到的最大高度)與 rmx(右指針右側含自身遇到的最大高度),動態決定當前應處理哪一端。
關鍵判斷在於比較 height[l] 與 height[r]:
- 若
height[l] < height[r],代表左側邊界較低。此時,無論右側內部情況如何,左指針位置l的右側最大高度必然大於或等於height[r],因此l位置的實際限制高度由lmx決定。故累加lmx - height[l]至總雨量,並將左指針右移。 - 反之,若
height[l] >= height[r],代表右側邊界較低或相等。同理,右指針位置r的左側最大高度必然大於或等於height[l],其限制高度由rmx決定。故累加rmx - height[r]至總雨量,並將右指針左移。
此策略確保在每一步中,我們只處理邊界較低的那一端,因為該端的積水量可以確定(另一側必然存在足夠高的屏障)。當兩指針相遇時,所有位置均被處理完畢。
通過的程式碼
class Solution:
def trap(self, height: List[int]) -> int:
ans = 0
l, r = 0, len(height)-1
lmx, rmx = 0, 0
while l< r:
lmx = max(lmx, height[l])
rmx = max(rmx, height[r])
if height[l] < height[r]:
ans += lmx - height[l]
l+=1
else:
ans += rmx - height[r]
r-=1
return ans