当青训营遇上码上掘金
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
这道题和接雨水是一道一模一样的题,因此我这里是直接copy的代码。
但是我引申一下,如果说柱子有正有负呢?该怎么去计算接豆子的个数呢?
1、先假设柱子全为正,求出柱子全为正,能接多少豆子
2、把每个负数高度柱子的绝对值加上去,得到最终的答案
步骤1 的思路:
- 先求出每个柱子左边的柱子中最高的柱子的高度
- 然后求每个柱子右边的柱子中最高的柱子高度
- 求出左右高度的柱子的最高高度意义是什么呢,当我遍历到i这个点,我求出i左右柱子高度的最大值的,最小值。再减去height[i]就能知道当前位置能装多少雨水。
通过这幅图也能看出,首先预处理左右柱子高度的最大值,然后进行On遍历,就能得到攒豆子的值。 当然这道题的原型是接雨水,只是改了个题面而已。
package main
import "fmt"
func main() {
arr := []int{5,0,2,1,4,0,1,0,3}
fmt.Println(trap(arr))
}
func trap(height []int) (ans int) {
n := len(height)
if n == 0 {
return
}
leftMax := make([]int, n)
leftMax[0] = height[0]
for i := 1; i < n; i++ {
leftMax[i] = max(leftMax[i-1], height[i])
}
rightMax := make([]int, n)
rightMax[n-1] = height[n-1]
for i := n - 2; i >= 0; i-- {
rightMax[i] = max(rightMax[i+1], height[i])
}
for i, h := range height {
ans += min(leftMax[i], rightMax[i]) - h
}
return
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}