Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.
Example 1:
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.
Example 2:
Input: height = [4,2,0,3,2,5]
Output: 9
这道题和常规的动态规划题目不一样,不容易用数学语言来表达,但仍可以借鉴动态规划的思路,由少至多计算出结果。
定义: 定义函数
f
(
i
)
f(i)
f(i)表示下标区间为
[
0
,
i
]
[0, i]
[0,i] 的柱子能接住的雨水数量。
已知: 第k根柱子的高度为
h
e
i
g
h
t
[
k
]
height[k]
height[k], 下标区间为
[
0
,
i
−
1
]
[0, i-1]
[0,i−1] 的柱子能接到的雨水数量为
f
(
i
−
1
)
f(i-1)
f(i−1)
引入变量: 在当前数组末尾追加1根柱子
分析影响: 第i根柱子的引入不会使之前已接到的雨水数量减少,新增加的数量为前面的柱子能映射到第i根柱子上的面积乘以柱子间的距离,假设用
g
(
i
)
g(i)
g(i) 来表示引入第i根柱子带来的新增水量,则题目的难度蜕变为求
g
(
i
)
g(i)
g(i)。
g
(
i
)
g(i)
g(i) 不是很好用数学公式来表达,如何推导在此不做赘述,大致思路是求水平方向上映射的阴影面积。
编程实现:
func trap(height []int) int {
area := 0
var crntH int
var crntW int
for i := 0; i < len(height); i++ {
if i < 2 {
continue
}
crntH = height[i-1]
for j := i - 2; j >= 0; j-- {
if height[j] <= crntH || height[i] <= crntH {
continue
}
crntW = i - j - 1
if height[j] < height[i] {
area += (height[j] - crntH) * crntW
crntH = height[j]
} else {
area += (height[i] - crntH) * crntW
break
}
}
println(area)
}
return area
}