当青训营遇上码上掘金
题目描述
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
解题思路
双指针法
- lm和rm初始分别表示左右两部分的最左边和最右边的柱子的高度。
- 通过比较左右两端的高度,选取值较小的柱子,往中间数青豆,每次移动一格。
- 选取容器中较小的柱子进行青豆计算是算法关键,需要二次条件判断,要保证两端(容器)柱子中较小的柱子,要比当前的柱子大,才能得到真正需要累加的青豆数,若当前柱子小于两端(容器)柱子中较小的柱子,就需要进行对最大左(右)柱子的高度的更新。
- 最后,ans的值在移动中进行累加,当l和r相等时,ans就是答案。
- 当左右两个指针为同一位置时,结束循环。
下面是我的代码片段,目前已经在码上掘金上发布:
以下为代码链接:主体4:攒青豆 - 码上掘金 (juejin.cn)
代码实现
func max(x, y int) int {
if x > y {
return x
}
return y
}
func solves(height []int) int {
ans := 0
if len(height) == 0 {
return ans
}
l := 0
r := len(height) - 1
lm := 0 //初始化
rm := 0 //初始化
for l < r {
lm = max(lm, height[l])//向左边移动得到的最大柱子高度
rm = max(rm, height[r])//向右边移动得到的最大柱子高度
if lm < rm { //储量只和最小的有关
ans += lm - height[l]
l++
} else {
ans += rm - height[r]
r--
}
}
return ans
}