当青训营遇上码上掘金

19 阅读2分钟

主题4:攒青豆

题目:

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

示例:

攒青豆.png

输入:height = [5,0,2,1,4,0,1,0,3]  
输出:17  
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

题目解析

这其实就是接雨水那道题了。。是一道力扣上典型的题目,面试也是热门,思路方法很多,这里采用双指针法便于理解。

先来分析一下题目:

我们一列一列的看,只有当柱子同时低于左右两边的柱子时,才会接上青豆,宽度为1,高度为高于当前柱子的两个柱子中矮的那边的柱子与当前列柱子的高度差。

思路:

我们可以在循环中先比较出左右柱子谁高,然后在从左或右计算高度差。则需要采用双指针法,同时进行两边,并对结果累加。

代码:


func collect(height []int) int {
   var left, right int     //左右柱子数组下标
   var lMax, rMax, res int //左右柱子最大值,结果
   right = len(height) - 1
   //双指针按列遍历柱子
   for left < right {
      if height[left] < height[right] {  //左边柱子小于右边柱子
         if height[left] >= lMax {
            lMax = height[left] // 设置左边最高柱子
         } else {
            res += lMax - height[left] // 当前为左边的柱子矮,则与左边的高度差即为当前柱子积攒的青豆,算入结果中
         }
         left++
      } else {
         if height[right] > rMax {
            rMax = height[right] //设置右边最高柱子
         } else {
            res += rMax - height[right] //与右边柱子高度差
         }
         right--
      }
   }
   return res
}

总结

解题方法还有单调栈等,水平有限不便讲解,算法题先要有思路最重要,双指针法在有思路的情况下还是能应付许多类型。当然,对于相似的题型就万变不离其宗了。