代码1.0-按列求:
- 每次找当前列左边的最大值,以及右边的最大值,其中,左右相对小的那个值减去当前列的值,就是当前列可以存放雨水的量
- 当然也不能直接减,因为为负值的时候,表示的应该是无法存放雨水,也就是存放雨水的量为0
- 所以减之前判断一下
func trap(he []int) int {
ans := 0
for i := 1; i < len(he)-1; i++ {
l := 0
for j := i-1; j >= 0; j-- {
if l < he[j] {
l = he[j]
}
}
r := 0
for j := i+1; j < len(he); j++ {
if r < he[j]{
r = he[j]
}
}
a := min(l, r)
if he[i] < a {
ans = ans + a - he[i]
}
}
return ans
}
func min(i,j int) int {
if i < j {
return i
}
return j
}
代码1.1按列求:
- 代码1.0中我们每次都for循环遍历找左和右的最大值,其实完全可以避免每次遍历
- 其中 L 我们可以保存最大值后,每次与新到的值做比较从而维护 L 。
- R 我们也可以用一个单调递减的队列维护其最大值,其中队列中存放下标,只要队首的下标还没有失效就把队首对应的he值赋值给R 就可以了,失效就弹出
func trap(he []int) int {
ans := 0
l := he[0]
rr := make([]int, 0)
push := func(i int) {
for len(rr) > 0 && he[i] >= he[rr[len(rr)-1]] {
rr = rr[:len(rr)-1]
}
rr = append(rr, i)
}
for i := 2; i < len(he); i++ {
push(i)
}
for i := 1; i < len(he)-1; i++ {
if l < he[i-1] {
l = he[i-1]
}
if rr[0] <= i {
rr = rr[1:]
}
r := he[rr[0]]
a := min(l, r)
if he[i] < a {
ans = ans + a - he[i]
}
}
return ans
}
func min(i,j int) int {
if i < j {
return i
}
return j
}
代码2-按行求:
图片来源,方法来源,原作者:leetcode.cn/problems/tr…
func trap(he []int) int {
ans := 0
max := getMax(he) //找到最大高度,以便遍历
for i := 1; i <= max; i++ {
var a bool
temp := 0 //标记是否开始更新temp,即temp已经遇到过一个大于当前i高度的值he[j]
for j := 0; j < len(he); j++ {
if a && he[j] < i {
temp++
}
if he[j] >= i {
ans += temp
temp = 0
a = true
}
}
}
return ans
}
func getMax (he []int) int {
max := 0
for i := 0; i < len(he); i++ {
if max < he[i] {
max = he[i]
}
}
return max
}