力扣中國 · #42

接雨水(Trapping Rain Water)

使用雙指針從兩端向中間掃描,透過比較兩端高度決定當前處理邊界,並利用已掃描區域的最大值計算該位置積水量,避免額外空間開銷。

開啟原題 ↗
時間複雜度O(n)
空間複雜度O(1)
解釋模型qwen/qwen3.8-27b

解題思路

本解法採用雙指針(Two Pointers)策略,從陣列兩端向中間收攏,以 O(1) 空間計算接水量。

核心邏輯基於「木桶效應」:每個位置能積蓄的雨水量,取決於其左側最大高度與右側最大高度中的較小值,再減去該位置本身的高度。然而,直接預計算左右最大值會消耗 O(n) 空間。此演算法透過維護兩個變數 lmx(左指針左側含自身遇到的最大高度)與 rmx(右指針右側含自身遇到的最大高度),動態決定當前應處理哪一端。

關鍵判斷在於比較 height[l] 與 height[r]:

  1. 若 height[l] < height[r],代表左側邊界較低。此時,無論右側內部情況如何,左指針位置 l 的右側最大高度必然大於或等於 height[r],因此 l 位置的實際限制高度由 lmx 決定。故累加 lmx - height[l] 至總雨量,並將左指針右移。
  2. 反之,若 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