当青训营遇上码上掘金
题目
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
示例:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
解法:单调栈
单调栈通过维持栈内值的单调递增(递减)性,在整体 O(n) 的时间内处理需要大小比较的问题。
代码
代码解析
为什么要使用单调栈:简单的想法就是如果当前的柱子高度比栈顶元素小就不能接豆子,需要把目前的柱子入栈。同时如果当前的柱子要比栈顶元素大说明可以接豆子,就需要进行出栈操作,计算可以接到的豆子结果。
这里有几个需要注意的点:
- 最开始的情况: 这个时候如果第一个柱子的高度是0,后一个柱子高度大于零,虽然满足我们一开始的设想但是也无法接豆子。即左边没有柱子的情况
代码示例:
// 如果栈空了,就结束循环;
if len(stack) == 0 {
break
}
- 获取矩形的高度:这里考虑一下木桶效应,水的高度决定于短的柱子,同时要减去栈顶元素 代码示例:
h := min(height[left], h) - height[top]
时间复杂度:O(n),其中 n 是切片 height 的长度。从 0 到 n-1 的每个下标最多只会入栈和出栈各一次。
空间复杂度:O(n),其中 n 是切片 height 的长度。空间复杂度主要取决于栈空间,栈的大小不会超过 n。