描述
给定n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
思路
暴力法:
求出每一列的左右列的最大值 maxLeft maxRight 在求出 min(maxLeft, maxRight) - height[i] 即为本列的雨水
动态规划:
暴力法基础上 动态规划 求maxLeft[i] = Max(maxLeft[i-1],height[i-1]) maxRight=Max(maxRight[i+1],height[i+1]
双指针:
指定left=1 right=l-1
maxLeft 代表的是0-left的最大值
maxRight 代表的是right - len-1的最大值
如果maxLeft < maxRight 说明 left 的左边最大值maxLeft 一定小于右边最大值 右边最大值不一定是maxRight 但一定小于 是不是我们不关心
如果maxLeft >= maxRight 说明 right 右边最大值 maxRight 一定小于right的左边最大值 但right左边最大值不一定是maxLeft 但一定小于 是不是我们不关心
实现
func Trap(height []int) int {
var ans int
cols := len(height)
for i := 1; i < cols-1; i++{
var maxLeft int
var maxRight int
var lower int
for j := 0; j < i; j++{
maxLeft = Max(maxLeft, height[j])
}
for j := i + 1; j < cols; j++{
maxRight = Max(maxRight, height[j])
}
lower = Min(maxLeft, maxRight)
if lower > height[i]{
ans = ans + lower - height[i]
}
}
return ans
}
func Trap2(height []int) int {
var ans int
cols := len(height)
maxLeft := make([]int, cols)
maxRight := make([]int, cols)
for i := 1; i < cols; i++{
maxLeft[i] = Max(maxLeft[i-1], height[i-1])
}
for i := cols - 2; i >= 0; i--{
maxRight[i] = Max(maxRight[i+1], height[i+1])
}
for i := 1; i < cols-1; i++{
var lower int
lower = Min(maxLeft[i], maxRight[i])
if lower > height[i]{
ans = ans + lower - height[i]
}
}
return ans
}
func Trap3(height []int) int {
var ans int
cols := len(height)
var left = 1
var right = cols - 2
var maxLeft int
var maxRight int
for left <= right{
maxLeft = Max(maxLeft, height[left - 1])
maxRight = Max(maxRight, height[right + 1])
if maxLeft < maxRight{
var lower = maxLeft
if lower > height[left]{
ans = ans + lower - height[left]
}
left++
}else{
var lower = maxRight
if lower > height[right]{
ans = ans + lower - height[right]
}
right--
}
}
return ans
}