当青训营遇上码上掘金-主题四攒青豆

46 阅读2分钟

当青训营遇上码上掘金

题目

针对于青训营主题四攒青豆,题目如下:

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

攒青豆.png

解题思路

对于一个最高的柱子,从某一方向开始向最高柱子前进,连续遇到的所有凹槽,其盛豆子总和正好对应这个方向的青豆数

而从左,从右分别向一个最高峰判定凹槽,计算的豆子总和正好是所有青豆数

而寻找凹槽,只需找比高于当前柱子的最近的那个即可,图中例子为 (3,4) (4,5) 两个凹槽

实现思路

判定凹槽可以用单调栈

对两个放向,用单调栈判断出每个索引向左右的最高值的索引,即 lhidx,rhidx 两个数组 (dir-higer-index)

回到图中,lhidx[8] = 4, lhidx[4] = 0,而rhidx[0] = -1

单调栈

monostack,顾名思义是栈内元素具有单调性,

在本题的用法,是寻找数组中某个元素(索引) 在某方向上 - 最近的 - 大于等于(或小于等于)它的元素(索引)

这个区间中,小于(或大于)它的元素都会被连续弹出monostack,直到形成单调性。

monostack的顶部元素(索引),就是寻找的 某个方向上 最近的 最值,例如:

 for(int i=0; i<n; i++){
        while(ldesc.size()>0 && h[ldesc.peek()] < h[i]) ldesc.pop(); // 弹掉小于的
        if(ldesc.size()>0) lhidx[i] = ldesc.peek(); // 留下大于等于的,-1的话说明没有
        ldesc.push(i);
    }

结论

所以,上述两放向凹槽的算法可以在O(n)时间求解

完整代码:code.juejin.cn/pen/7199604…