当青训营遇上码上掘金,攒青豆题目:现在有n个宽度为1的柱子,给出n个非负整数依次来表示柱子的高度,排列后如下图所示。此时均匀从上空向下撒下青豆,要求计算按此排列的柱子能够接住多少青豆。(不考虑边角堆积)
解题思路:单调栈
观察图片我们可以发现,攒住豆子的地方形状为一个凹槽,有着中间低,两边高的特征。计算每个地方的豆子等于计算凹槽切面的面积。那么我们怎么在每次出现凹槽的时候,让程序计算处理呢?这时候便需要用到单调栈这一结构。单调栈指的是在栈中,从栈底到栈顶的元素大小是单调变化的。举个例子,如果单调栈从栈底到栈顶为从大到小,那么有比栈顶大的元素需要入栈时,便需要把栈中比他小的元素都弹出,随后再入栈,从而保证栈内从大到小的单调顺序。
那么在这题里,我们的单调栈从栈底到栈顶的顺序,应该是从大到小还是从小到大呢?回想一下上面的分析,当出现凹槽(两边高,中间低)时,需要计算更新。这种情况正好对应的是从大到小的单调栈,因为左边的元素一定比右边的元素高,而当有比栈顶元素更大的元素入栈时,此时则满足了两边高,中间(栈顶)低的情况。出现这一种情况时,我们需要获取左右两边和中间的高度差,根据木桶效应,该高度差为min(左边高度,右边高度) - 中间高度
。宽度差则为凹槽的长度,它等于右边的索引-左边的索引-1
。
代码片段
下面来看具体的代码实现: