42. Trapping Rain Water
題目網址:https://leetcode.cn/problems/trapping-rain-water/
題意:給
n個非負整數, 代表每個寬度為1的柱子之高度圖, 計算按此排列的柱子, 在下雨後能接多少雨水。

Solution 1:(TLE 無法通過)
想法:利用暴力法, 我們計算每個 col 所能接住的水量, 因此對於每個
i我們要在height[0 ~ i]和height[i ~ (n - 1)]中分別找出最大值leftMax和rightMax, 則該 col 所能接住的水量 =min(leftMax, rightMax) - height[i]
class Solution { |
- time:$O(n^2)$ ➔ 每計算一次需找出
leftMax和rightMax, 此過程需 $O(n)$, 總共要計算n次 - space:$O(1)$ ➔ 只需常數空間
Solution 2:
想法:利用 DP, 概念同 Solution 1, 只是我們用兩個 array
leftMax和rightMax來記錄, 其中leftMax[i]和rightMax[i]分別代表height[0 ~ i]和height[(n - 1) ~ i]之最大值
- 由左往右遍歷
height得到每一個leftMax[i]- 由右往左遍歷
height得到每一個rightMax[i]- 最後計算每個 col 所能接住的雨水
class Solution { |
- time:$O(n)$ ➔ for loop
- space:$O(n)$ ➔
leftMax,rightMax
Solution 3:
想法:利用 Two Pointers, 改進 Solution 2, 因為
leftMax[i]和rightMax[i]只會用到一次, 然後就再也不會用到了, 因此我們用一個變數記住即可。我們定義以下變數:
leftMax:左邊的最大值, 它是由左往右遍歷得到的rightMax:右邊的最大值, 它是由右往左遍歷得到的left:由左往右處理的當前 idxright:由右往左處理的當前 idx我們有以下定理可使用:
定理一:在
idx = i時能接住的水量是取決於左右兩邊的最大值中較小的那一個定理二:
- 當我們由左往右處理到
left時, 左邊的最大值leftMax對它而言是可信的, 但rightMax對它而言是不可信的- 當我們由右往左處理到
right時, 右邊的最大值rightMax對它而言是可信的, 但leftMax對它而言是不可信的
由上述定理, 我們可以得到:
- 對於
left而言, 它左邊最大值一定是leftMax, 就算右邊實際最大值 ≥ rightMax, 只要leftMax < rightMax成立, 就能知道left能接住多少水(定理一), 無論右邊將來是否會出現更大的rightMax, 都不會影響到這個結果。反之,right也是同樣道理。while loop 的條件為何是
left <= right, 而非left < right?因為是先計算當前 ptr, 再移動 ptr 的
e.g.
height = [1, 0, 3]
- 一開始
leftMax(0) < rightMax(0)不成立, 故處理right➔ 得rightMax = 3,res = 0,right = 1leftMax(0) < rightMax(3)成立, 故處理left➔ 得leftMax = 1,res = 0,left = 1- 此時,
left = 1 = right, 若 while loop 條件為left < right, 則無法計算到idx = 1位置的水量leftMax(1) < rightMax(3)成立, 故處理left➔ 得leftMax = 1,res = 1,left = 2
class Solution { |
- time:$O(n)$ ➔ while loop 遍歷
height - space:$O(1)$ ➔ 只需常數空間
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Zako's Blog!
評論

