当青训营遇上码上掘金
题目4攒青豆代码以及思路分享
题目
-
主题 4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 单位的青豆。
题解
本题的主要解决思路是单调栈——从大到小,题目要求计算出攒下的青豆数量,实质上是计算凹槽的面积,比如计算柱子高度为5到柱子高度为4之间的面积,计算过程为:5和2之间的面积2+2和4之间的面积1+4和5之间的面积6=9,宽度即为柱子下标之差再减1,高度为当前柱子减去中间柱子。单调栈的思路是当前元素比栈顶元素大,栈顶元素出栈,当前元素入栈进行结果计算,直至当前元素成为栈底元素或小于栈顶元素。如果当前元素比栈顶元素小,直接把下标入栈即可。单调栈解题思路模板如下:
代码
主体代码展示如下:
func saveGreenBeans(pillars []int) (ans int) {
var stack []int
for i, v := range pillars {
// 当前元素比栈顶大,即找到下一个更大元素,弹出栈顶,更新结果
for len(stack) > 0 && v > pillars[stack[len(stack)-1]] {
mid := stack[len(stack)-1]
stack = stack[:len(stack)-1]
// 更新结果
// 取出左柱索引
left := stack[len(stack)-1]
// 计算高度以及宽度
height := minValue(pillars[left], v) - pillars[mid]
width := i - left - 1
// 累加计算面积
ans += height * width
}
// 当前元素比栈顶小,直接把下标入栈
stack = append(stack, i)
}
return ans
}
func minValue(a, b int) int {
if a < b {
return a
}
return b
}
总结
算法之路任重而道远,希望大家持之以恒、坚持不懈,大家一起加油、共同努力吧!