[青训营 X 码上掘金] 主题4:赞青豆

47 阅读2分钟

当青训营遇上码上掘金

题目

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

725ef710a59944d49d0315bece7a1ac1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp 示例: 输入:height = [5,0,2,1,4,0,1,0,3]

输出:17

解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

解法:单调栈

单调栈通过维持栈内值的单调递增(递减)性,在整体 O(n) 的时间内处理需要大小比较的问题。

代码

代码解析

为什么要使用单调栈:简单的想法就是如果当前的柱子高度比栈顶元素小就不能接豆子,需要把目前的柱子入栈。同时如果当前的柱子要比栈顶元素大说明可以接豆子,就需要进行出栈操作,计算可以接到的豆子结果。

这里有几个需要注意的点:

  1. 最开始的情况: 这个时候如果第一个柱子的高度是0,后一个柱子高度大于零,虽然满足我们一开始的设想但是也无法接豆子。即左边没有柱子的情况

代码示例:

// 如果栈空了,就结束循环;
if len(stack) == 0 {
   break
}
  1. 获取矩形的高度:这里考虑一下木桶效应,水的高度决定于短的柱子,同时要减去栈顶元素 代码示例:
h := min(height[left], h) - height[top]

时间复杂度:O(n),其中 n 是切片 height 的长度。从 0 到 n-1 的每个下标最多只会入栈和出栈各一次。

空间复杂度:O(n),其中 n 是切片 height 的长度。空间复杂度主要取决于栈空间,栈的大小不会超过 n。