文章目录
- 二、栈和队列
- 2.1 基本应用
- 2.1.1 逆波兰表达式求值
- 2.1.2 有效的括号
- 2.2 单调栈
- 2.2.1 柱状图中最大的矩形
二、栈和队列
2.1 基本应用
2.1.1 逆波兰表达式求值
150. 逆波兰表达式求值
class Solution {
/**
思路分析:
遇到数则压栈,遇到运算符则用最上层的两个数进行运算并将结果压栈
*/
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
int n1,n2;
for(String token : tokens){
switch(token){
case "+":
// 加法
n1 = stack.pop();
n2 = stack.pop();
stack.push(n1+n2);
break;
case "-":
// 减法
n1 = stack.pop();
n2 = stack.pop();
stack.push(n2-n1);
break;
case "*":
// 乘法
n1 = stack.pop();
n2 = stack.pop();
stack.push(n1*n2);
break;
case "/":
// 除法
n1 = stack.pop();
n2 = stack.pop();
stack.push(n2/n1);
break;
default:
stack.push(Integer.parseInt(token)); // 为数字则压栈
break;
}
}
return stack.pop();
}
}
2.1.2 有效的括号
20. 有效的括号
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
char[] chars = s.toCharArray();
char cc;
for(char c : chars){
if(stack.isEmpty() || c=='(' || c=='{' || c=='['){
stack.push(c);
continue;
}
cc = stack.peek();
if((cc == '(' && c == ')') || (cc == '{' && c == '}') || (cc == '[' && c == ']')){
stack.pop();
}else{
stack.push(c);
}
}
return stack.isEmpty();
}
}
2.2 单调栈
单调栈:栈内元素保持单点递增或单调递减的栈
(以单调递增为例)
入栈规则:
- 新元素比栈顶元素小:直接入栈
- 新元素比栈顶元素大:弹出栈内元素直到栈顶比新元素小(或空栈)
出栈意义: - 需要出栈时,入栈的新元素是出栈元素有房第一个比出栈元素小的元素
- 出栈后,新的栈顶是出栈元素左侧最大的数
技巧:最后添加一个值为0的哨兵结点,可以在最后强制所有元素出栈。
以下分别使用了单调递增栈
和单调递减栈
2.2.1 柱状图中最大的矩形
84. 柱状图中最大的矩形
class Solution {
public int largestRectangleArea(int[] heights) {
// 定义栈
Stack<Integer> stack = new Stack<>();
int max = 0;
for(int i = 0;i <= heights.length;i++){
int curHeight;
if(i == heights.length){
curHeight = 0; // 使用哨兵使栈中元素全部出栈
}else{
curHeight = heights[i];
}
while(!stack.isEmpty() && curHeight < heights[stack.peek()]){
int ph = heights[stack.pop()];
while(!stack.isEmpty() && heights[stack.peek()] == ph){
stack.pop(); // 相同高度时,定位至最左侧的数
}
/**
计算从右向左依次中间高度的右边界(即当前高度的下标)与左边界(栈中当前元素的前一个位置)之差。
注意没有左边界的情况(即当前单调栈只有一个元素)
*/
int w = i - (stack.isEmpty() ? -1 : stack.peek()) - 1;
max = Math.max(max,ph*w);
}
stack.push(i);
}
return max;
}
}