链接:42. 接雨水 - 力扣(LeetCode) (leetcode-cn.com)
本题将采用单调栈的思想来解
给定
n
个非负整数表示每个宽度为1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
思路:
利用一个栈,这个栈是从低到高依次递减的单调栈
先将第一个柱子放入栈,以方便后续操作
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
后面来的的柱子如果高度更低,直接放入栈
if (height[stack.peek()] > height[i]){
stack.push(i);
}
如果相等,需要先弹出,再放入这个相等的值
if (height[stack.peek()] == height[i]){
stack.pop();
stack.push(i);
}
如果大于,说明有凹槽可以存放雨水了,目前栈顶元素就是凹槽的最中心mid,先取出
取出后需要计算雨水的面积
雨水高度就是左右柱子最小的高度减去mid的高度
雨水宽度就是右柱子的下标减去左柱子的下标再减1
这里需要用一个while循环,因为可能会一直大于
if (height[stack.peek()] < height[i]) {
while (!stack.isEmpty() && height[i] > height[stack.peek()]){
int mid = stack.pop();
if (!stack.isEmpty()){//这里需要一个判空,因为防止柱子在最左边的情况
int h = Math.min(height[stack.peek()], height[i]) - height[mid];
int w = i - stack.peek() - 1;
ans += h * w;
}
}
stack.push(i);
}
最终代码
class Solution {
public int trap(int[] height) {
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int ans = 0;
for (int i = 1; i < height.length; i++){
if (height[stack.peek()] > height[i]){
stack.push(i);
}else if (height[stack.peek()] == height[i]){
stack.pop();
stack.push(i);
}else {
while (!stack.isEmpty() && height[i] > height[stack.peek()]){
int mid = stack.pop();
if (!stack.isEmpty()){
int h = Math.min(height[stack.peek()], height[i]) - height[mid];
int w = i - stack.peek() - 1;
ans += h * w;
}
}
stack.push(i);
}
}
return ans;
}
}