当青训营遇上码上掘金
链接:juejin.cn/post/718775…
主题 4:攒青豆:
题目
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
解题思路
本题可以通过单调栈来实现。
维护一个单调栈,单调栈存储的是下标,满足从栈底到栈顶的下标对应的数组 height 中的元素递减。
从左到右遍历数组,遍历到下标 i 时,如果栈内至少有两个元素,记栈顶元素为 top,top 的下面一个元素是 left,则一定有 height[left]≥height[top]。如果 height[i]>height[top],则得到一个盛放青豆的区域,该区域的宽度是 i-left−1,高度是 min(height[left],height[i])−height[top],根据宽度和高度即可计算得到该区域能盛放青豆的数量。
为了得到 left,需要将 top 出栈。在对 top 计算能盛放的青豆数目之后,left 变成新的 top,重复上述操作,直到栈变为空,或者栈顶下标对应的 height 中的元素大于或等于 height[i]。
再对下标 i 处计算能盛放的青豆数目之后,将 i 入栈,继续遍历后面的下标,计算能盛放的青豆数目。遍历结束之后即可计算得到所能存放的青豆数目。
相关代码
复杂度分析
时间复杂度:O(n),其中 n 柱子的数目(即数组 heights 的长度)。从 0 到 n−1 的每个下标最多只会入栈和出栈各一次。
空间复杂度:O(n),其中 n 柱子的数目(即数组 heights 的长度)。空间复杂度主要取决于栈空间,栈的大小不会超过 n。