当青训营遇上码上掘金 | 攒青豆

158 阅读2分钟

当青训营遇上码上掘金

题目4攒青豆代码以及思路分享

题目

  • 主题 4:攒青豆

    现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

image.png 以下为上图例子的解析: 输入: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,高度为当前柱子减去中间柱子。单调栈的思路是当前元素比栈顶元素大,栈顶元素出栈,当前元素入栈进行结果计算,直至当前元素成为栈底元素或小于栈顶元素。如果当前元素比栈顶元素小,直接把下标入栈即可。单调栈解题思路模板如下:

image.png

代码

code.juejin.cn/api/raw/719…

主体代码展示如下:

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
}

总结

算法之路任重而道远,希望大家持之以恒、坚持不懈,大家一起加油、共同努力吧!