题:接雨水
本题单调栈的作用:1.便于获取top的左墙;2.便于寻找右墙
class Solution {
public int trap(int[] height) {
int len=height.length;
int res=0;
//利用双向队列实现“单调递减的栈”(栈内存放的是序号,栈顶元素最小)
//因为需要维护单调栈,才会有出栈的操作
Deque<Integer> stack=new LinkedList<>();
for(int i=0;i<len;i++){
//当当前高度大于时,就不满足单调性了,所以不能直接加入
//可能height[i]大于栈中的好几个元素,所以需要while循环
while(!stack.isEmpty() && height[i]>height[stack.peek()]){
//首先出栈(获取top下面的left左墙),栈中至少两个元素才有意义
int top=stack.pop();
//如果top没有左墙,也就没法保存雨水
if(!stack.isEmpty()){
int left=stack.peek();//注意这里是peek(),可能这个left的高度小于height[i]
int broadLen=i-left-1;
int hLen=Math.min(height[i],height[left])-height[top];
res=res+broadLen*hLen;
}
}
//满足单调性,序号直接加入栈中(height[i]小于等于栈顶元素才开始入栈)
stack.push(i);
}
return res;
}
}
题:每日温度
当前元素大于栈顶元素,说明当前元素是栈顶元素的后面的第一个更高温度的天,就可以求出栈顶元素的answer
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int len=temperatures.length;
int[] answer=new int[len];
//使用单调栈(递减栈来实现),如果小于等于栈顶的元素就直接入栈
Deque<Integer> stack=new LinkedList<>();
for(int i=0;i<len;i++){
int curtemp=temperatures[i];
//如果当前元素大于栈顶元素,那么这个栈顶元素的answer就可以求了
//可能这个元素是栈中好几个元素的高温天
while(!stack.isEmpty() && curtemp>temperatures[stack.peek()]){
int left=stack.pop();
answer[left]=i-left;
}
stack.push(i);
}
return answer;
}
}
题:柱子图中的最大矩形(左右的两遍单调栈的情况)
class Solution {
public int largestRectangleArea(int[] heights) {
int len=heights.length;
int res=0;
int[] leftQ=new int[len];//寻找左边界(刚好左边第一个小于本位置高度的序号)
int[] rightQ=new int[len];//寻找右边界(刚好右边第一个小于本位置高度的序号)
//利用一个单调递增的栈,寻找左边界(刚好左边第一个小于本位置高度的序号)
Deque<Integer> stack=new LinkedList<>();
for(int i=0;i<len;i++){
//寻找小于heights[i]的元素的序号
while(!stack.isEmpty() && heights[i]<=heights[stack.peek()]){
stack.pop();
}
leftQ[i]=stack.isEmpty()?-1:stack.peek();//如果栈为空,说明它没有左边比它小的墙(哨兵:-1--是的,不满足的第一个序号)
stack.push(i);
}
stack.clear();//清楚所有的元素(复通这个栈)
//利用一个单调递增的栈,寻找右边界(刚好右边第一个小于本位置高度的序号)
for(int i=len-1;i>=0;i--){
//寻找小于heights[i]的元素的序号
while(!stack.isEmpty() && heights[i]<=heights[stack.peek()]){
stack.pop();
}
rightQ[i]=stack.isEmpty()?len:stack.peek();//如果栈为空,说明它没有右边比它小的墙(哨兵:len--是的,不满足的第一个序号)
stack.push(i);
}
for(int i=0;i<len;i++){
res=Math.max(res,(rightQ[i]-leftQ[i]+1-2)*heights[i]);
}
return res;
}
}