题目要求
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路分析
首先要成功装下一单位的青豆,我们需要左右两方同时有一格高的柱子存在(不论间隔)。故我们需要从两个方向寻找最高的柱子,计算出这之间满足左右两方同时存在柱子所构成的高度,并且需要减去原本存在的柱子高度,才能得到正确的可容纳的青豆单元数。
以这样的思路,我们需要:
- 两个循环:从左右两方扫描并记录最大高度。
- 第三个循环:切去单侧的独柱,并减去原本存在的柱子高度,得到正确的结果。
既然参加了这次的青训营,我们就用Go实现
额外的,由于Go没有类似于变长数组的概念以及max() min()这样的方法,我们需要用到Slice来代替变长数组,并自己定义max() min()。
func trap(height []int) (FinalBeans int) {
n := len(height)
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 {
FinalBeans += 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
}
当然,此种方法并不是最好的算法,但是思路直观,更容易想到。此题和接雨水极为相似,可自行搜索,这里不再赘述。