这道题是困难,但是可以使用单调栈,非常简洁通俗。
关于单调栈可以参考单调栈总结以及Leetcode案例解读与复盘
42. 接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
思路:首先理解题意
我们需要接雨水,所以必然是会要形成一个凹槽,因此我们只要构建一个单调递减栈,(凹槽的左边),当遇到大于栈顶元素的元素时,说明可以开始计算接的雨水的面积。直接通过下图理解更好理解。
这里有几个需要注意的:
- 首先,和坐标轴是没有办法接雨水的
- 在找凹槽的左边界时,需要先将栈顶元素弹出,因此做完一次计算的操作后,left变成了栈顶元素,原先的栈顶元素已经被弹出
- 因为将栈底元素已经弹出了,因此我们在计算面积的时候也不会重复,具体看上图面积黄色色块。
代码实现
var trap = function (height) {
// 遍历,构造单调递减的单调栈,一旦遇到递增,就开始加
let stack = [];
let ans = 0;
for(let i = 0; i < height.length; i++){
while(stack.length && height[i] > height[stack.at(-1)]){
// 可能出现凹地,寻找left
let peek = stack.pop();
let left = stack.length ? stack.at(-1) : -1;
if(left !== -1){
let width = i - left - 1;
let h = Math.min(height[left], height[i]) - height[peek];
ans += width * h;
}
}
stack.push(i);
}
return ans;
}
console.log(trap([0,4,2,0,3,2,5]))
类似习题:
【LeetCode每日一题】 单调栈的案例84 柱状图中最大的矩形