Solution 1
- 參考 Trapping Rain Water - Neetcode
- 每一個 index 能承裝的水量,取決於左邊的最高點 maxLeft 和右邊的最高點 maxRight,maxLeft 跟 maxRight 中比較小的值代表是兩邊圍起來的高度。
- 根據上面的定義,可以建立兩個陣列 maxLeft 看 maxRight,分別代表每個 index 的左邊最高點和右邊最高點是多少。
- 最後把全部的 height 跑過一遍,把圍起來的高度 min(maxLeft[i], maxRight[i]) 扣掉 height[i] 就是這個 index 能裝的水,全部加起來就是解答。
- Time: O(N), Space: O(N)
Implementation
class Solution {
fun trap(height: IntArray): Int {
val n = height.size
val maxLeft = IntArray(n)
val maxRight = IntArray(n)
for (i in 1 until n) maxLeft[i] = max(maxLeft[i-1], height[i-1])
for (i in n-2 downTo 0) maxRight[i] = max(maxRight[i+1], height[i+1])
var result = 0
for (i in 0 until n) {
val water = min(maxLeft[i], maxRight[i]) - height[i]
if (water > 0) result += water
}
return result
}
}
Solution 2
- 參考 Trapping Rain Water - Neetcode
- 優化 Solution 1 空間的做法,就要減少 maxLeft 和 maxRight 的儲存空間。
- 因此可以改用 Two Pointer 的方式記錄兩邊的位置,l 和 r 分別從左右兩端往中間移動,每次移動 maxLeft maxRight 比較小的指針。
- 移動完計算這個 index 的水量 min(maxLeft, maxRight) - height[i],再更新 maxLeft/maxRight。全部的水量加起來就是解答。
- Time: O(N), Space: O(1)
Implementation
class Solution {
fun trap(height: IntArray): Int {
var (l, r) = 0 to height.lastIndex
var (maxLeft, maxRight) = height[l] to height[r]
var result = 0
while (l < r) {
if (height[l] < height[r]) {
result += max(min(maxLeft, maxRight) - height[++l], 0)
maxLeft = max(maxLeft, height[l])
} else {
result += max(min(maxLeft, maxRight) - height[--r], 0)
maxRight = max(maxRight, height[r])
}
}
return result
}
}