「青训营 X 码上掘金」题目4:攒青豆

90 阅读2分钟

[√] 当青训营遇上马上掘金

题目:攒青豆

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

青豆.webp

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

解答:

观察可以发现,能接住豆子的部分主要是以最左最右两侧为边,接住豆子的多少取决于两个边中较矮的那个。因此该题可以遍历数组,查找能形成凹槽的柱子的两个边,计算接住的豆子。(接雨水)

  • 可以先列列举如下情况,得到接青豆的一个场景:
    1.找到左右两侧柱子较矮的那个
    2.从左右较矮的开始遍历
    3.获知中间所有柱子的高度,求和比左右中矮柱子更矮的柱子高度,将在最后计算个数时减掉
    4.找到比他高的,这里就是第一个凹槽,计算面积
    5.以这个找到的柱子为基础,再次找比他高的重复上一个步骤
    6.循环直到遍历到找柱子的数组索引到左右一侧边界或左右柱子索引相等为止

  • 合并条件:
    1.(1.4.)
    2.(2.3.)
    3.其余
    每次找到一个凹槽后都将重新判断一次未遍历区域左右边界

当然与上述思路对称找最高也是可以的

代码:

function solution(height) {

  let sum = 0;

  for (let i = 1; i < height.length - 1; i += 1) {

    let maxleft = height[0];
    let maxright = height[height.length - 1];

    for (let j = 1; j < i; j += 1) {
      if (height[j] > maxleft) {
        maxleft = height[j];
      }
    }

    for (let j = i + 1; j < height.length - 1; j += 1) {
      if (height[j] > maxright) {
        maxright = height[j];
      }
    }

    let minmax = Math.min(maxleft, maxright);

    if (height[i] < minmax) {
      sum += minmax - height[i];
    }
  }
  return sum
}

码上掘金展示