|-------------|--------------|-----------------|
| push | 压栈,将元素放入栈顶 | push(e) |
| pop | 弹栈,移除并返回栈顶元素 | pop() |
| peek | 查看栈顶元素(不移除) | peek() |
| isEmpty | 判断栈是否为空 | isEmpty() |
| size | 获取栈中元素个数 | size() |
| 坑点 | 说明 | 解决方案 |
|---|---|---|
| pop/peek 前未判空 | 空栈调用会抛 EmptyStackException |
用前检查 !stack.isEmpty() |
用 == 比较 Integer |
比较两个 Integer 对象用 == 会出问题 |
用 .equals() |
| 忘记更新栈状态 | 只判断未弹出,导致死循环 | 确保 pop() 正确调用 |
| 单调栈边界 | 栈空时的 peek/pop 操作 | 用 isEmpty() 判断 |
| Deque 的 push/pop 与 addFirst/removeFirst | 两套方法等价,但混用可能混淆 | 统一用 push/pop/peek 语义 |
| 场景 | 核心思想 | 经典题目 |
|---|---|---|
| 括号匹配 | 遇到左括号压栈,遇到右括号弹出匹配 | LeetCode 20 |
| 表达式求值 | 操作数栈 + 运算符栈,处理优先级 | LeetCode 150 |
| 单调栈 | 维护单调递增/递减栈,找下一个更大/更小元素 | LeetCode 739, 42, 84 |
| DFS(深度优先搜索) | 用栈模拟递归,避免递归栈溢出 | LeetCode 94 |
| 撤销操作(Undo) | 每步操作压栈,撤销时弹出 | 系统设计题 |
| 浏览器前进后退 | 两个栈配合,前进栈 + 后退栈 | 系统设计题 |
自动装箱:
java
// 自动装箱:int → Integer
Integer a = 100; // 等价于 Integer.valueOf(100)
// 自动拆箱:Integer → int
int b = a; // 等价于 a.intValue()
// 在集合中自动装箱
Deque<Integer> stack = new ArrayDeque<>();
stack.push(512); // int 512 自动装箱成 Integer
int val = stack.pop(); // Integer 自动拆箱成 int
基本语句:
java
import java.util.*;
public class StackDemo {
public static void main(String[] args) {
// 1. 创建栈
Deque<Character> stack = new ArrayDeque<>();
// 2. 压栈 push
stack.push('a');
stack.push('b');
stack.push('c');
System.out.println(stack); // [a, b, c](栈顶在右)
// 3. 查看栈顶 peek
char top = stack.peek();
System.out.println(top); // c(不出栈)
// 4. 弹栈 pop
char popped = stack.pop();
System.out.println(popped); // c
System.out.println(stack); // [a, b]
// 5. 判空 isEmpty
boolean empty = stack.isEmpty();
System.out.println(empty); // false
// 6. 获取大小 size
int size = stack.size();
System.out.println(size); // 2
// 7. 清空栈(方法一:逐个弹出)
while (!stack.isEmpty()) {
stack.pop();
}
// 8. 清空栈(方法二:clear)
// stack.clear();
System.out.println(stack.isEmpty()); // true
}
}
20-有效的括号
**思路:**遍历每个字符,先把左括号压入栈,到右括号时出栈进行对比。
**注意:遍历s用toCharArray()**来变成单字符数组;
判断右括号,要考虑特殊情况 即栈空;
整体返回 不直接返true ,万一奇数个括号,因此返回**stack.isEmpty.()**是否为空
java
class Solution {
public boolean isValid(String s) {
Deque <Character> stack=new ArrayDeque<>();
//左括号压入栈,右括号匹配就出栈
for(char c:s.toCharArray()){ //将s换成字符数组
if(c=='('||c=='['||c=='{'){//判断左括号,入栈
stack.push(c);
}else{//判断右括号
if(stack.isEmpty()){ //栈为空,即无对应左括号
return false;
}
char pop= stack.pop();//出栈判断是否左右匹配
if(!isMatch(pop,c)){
return false;
}
}
}
return stack.isEmpty();//栈为空,即偶数,则全部匹配成功
}
public boolean isMatch(char pop,char c){
if(pop=='('&&c==')'||pop=='['&&c==']'||pop=='{'&&c=='}'){
return true;
}else{return false;}
}
}
155-最小栈
**思路:按要求来,新建minstack来存历史最小值,最顶部就是当前最小值,只要更小就入minstack,所以其是越来越小。获取最小值直接minstack.peek()**就行
注意:int是披萨(值) ,Integer是披萨盒(地址),两者比较用.equals() 比较值,用**=**是判断两个地址是否相等,Deque等不接受int,只接受Integer盒子;
stack.pop()在if条件里就算执行了一次pop,不需要再写pop操作了;
如果没有最小值这个概念要求,直接 stack.pop(),就行了
java
class MinStack {
Deque <Integer>stack;
Deque <Integer>minstack;
public MinStack() {
stack=new ArrayDeque<>();
minstack=new ArrayDeque<>();
}
public void push(int val) {
stack.push(val);
if(minstack.isEmpty()||val<=minstack.peek()){//minstack为空 或 <当前最小值
minstack.push(val);
}
}
public void pop() {
if(stack.pop().equals(minstack.peek())){ //pop的与minstack顶部(当前最小值)相等时
minstack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return minstack.peek();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
394-字符串解码
思路:
遍历每个字符:
数字 → 累加 num
字母 → 拼到当前结果 curr
→ 把 num 和 curr 压栈,然后重置 num=0, curr=""
\] → 弹出 num 和 栈顶字符串,把 curr 重复 num 遍,再拼到栈顶字符串后面
**注意:**StringBuilder是可变字符串;
**注意StringBuilder、String和char的格式,必须统一;**
String是定长,StringBuilder是可变长;
num入栈出栈之后要置0;
需要使用temp来接住从栈里弹出来的字符串,方便重复操作,重复完变成当前值cur ;
```java
class Solution {
public String decodeString(String s) {
Deque





