当青训营遇上码上掘金
题目
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
思路一 单调栈
考虑想要获得青豆,就必须是当前位置的左边和右边都有比他高度高的值才行。这样当前位置能够获取的青豆就是左边和右边最大值中的最小值减去当前位置的高度。
我们先考虑单调栈,单调栈里面存数组下标,栈底到栈顶数组下标对应的高度从高到低递减。然后遍历整个数组,假如当前下标的高度大于栈顶高度,取出栈的第二个值(也就是栈顶左边的那个柱子的高度),计算这个值到当前位置这个区间的贡献进行加和。
这样计算也就相当于每次考虑一行进行加和。时间复杂度上,遍历数组一次,每个下标入栈、出栈各一次;空间复杂度上,需要使用栈存储数组下标,最坏情况下需要将所有下标全部入栈(原数组单调递减)。
时间复杂度:O(n)
空间复杂度:O(n)
代码如下
思路二 双指针
下面是每次考虑一列进行加和。
我们使用双指针,一个在最左边,一个在最右边,同时记录左边最大值和右边最大值。考虑左边和右边最大值,谁的值更小,谁向里移动,逐个加和就可以和获得答案了,这样就不需要将所有下标都存下来了。
时间复杂度上,总共遍历数组一次;空间复杂度上,只是用常数个变量。
时间复杂度:O(n)
空间复杂度:O(n) 代码如下