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 = 1
leftMax(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!
評論