[青训营 X 码上掘金] 主题4: 攒青豆

63 阅读2分钟

当青训营遇上码上掘金

题目描述

现有 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 个单位的青豆。

解题思路

双指针法

  • 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
}

运行结果

image.png