接雨水
- leetcode42. 接雨水
- 题目描述
- 单调栈解题
- 代码演示
- 单调栈专题
leetcode42. 接雨水
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/trapping-rain-water
题目描述
给定 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
提示:
n == height.length
1 <= n <= 2 * 10000
0 <= height[i] <= 10000
单调栈解题
单调栈其实就是在栈的基础上,维持一个栈内元素单调。
在这道题,由于需要找某个位置两侧比其高的柱子(只有两侧有比当前位置高的柱子,当前位置才能接下雨水),我们可以维持栈内元素的单调递减。
找某侧最近一个比其大的值,使用单调栈维持栈内元素递减;找某侧最近一个比其小的值,使用单调栈维持栈内元素递增 …
当某个位置的元素弹出栈时,例如位置 a ,我们自然可以得到 a 位置两侧比 a 高的柱子:
一个是导致 a 位置元素弹出的柱子( a 右侧比 a 高的柱子)
一个是 a 弹栈后的栈顶元素(a 左侧比 a 高的柱子)
当有了 a 左右两侧比 a 高的柱子后,便可计算 a 位置可接下的雨水量。
我们可以用数组来优化栈结构,这样常数时间效率更高.
代码演示
/**
* 接雨水
* @param height
* @return
*/
public int trap(int[] height) {
if (height == null || height.length < 3){
return 0;
}
int N = height.length;
int[]stack = new int[N];
int stackSize = 0;
int ans = 0;
for (int i = 0; i < N;i++){
while (stackSize != 0 && height[i] > height[stack[stackSize - 1]]){
int cur = stack[--stackSize];
//stackSize == 0 说明左边没有值,无法接雨水,直接结束当前循环
if (stackSize == 0){
break;
}
//左边柱子在的位置
int l = stack[stackSize - 1];
//宽度
int w = i - l - 1;
//高度
int h = Math.min(height[l],height[i] ) - height[cur];
ans += (w * h);
}
stack[stackSize++] = i;
}
return ans;
}
单调栈专题
leetcode1856. 子数组最小乘积的最大值
leetcode84. 柱状图中最大的矩形
leetcode.85. 最大矩形