当青训营遇上码上掘金。
题目:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路分析
攒青豆这道题中,可采用单调栈的实现方式。这种解法的基本思想是确保保存在栈中的柱子高度是递减排序的。 单调递减栈
按照题目的描述,当后面的柱子高度比前面的低时,是无法接住青豆的,而当找到一根比前面高的柱子,就可以计算接到的雨水。 因此,我们使用单调递减栈,对更低的柱子入栈。更低的柱子认为在之后如果出现高柱子,这里就能接到雨水,所以入栈把它保存起来。高度 0 的柱子相当于平地,不需要做额外处理。
当出现高于栈顶的柱子时,说明可以对前面的柱子计算。由于栈中柱子的高度是递减排序的,因此位于栈顶前面的一根柱子一定比位于栈顶的柱子高,于是很容易找到位于栈顶柱子两侧比他高的柱子。
青豆的区域全部确定了,青豆的高度就是左右两边更低的一边减去底部,宽度是在左右中间的长度。使用乘法即可计算面积,计算式如下。
res += (Math.min(height[stack.peek()], height[i])-height[cur]) * (i-stack.peek()-1);