栈算法10道经典例题(Java实现)
覆盖基础栈、单调栈、辅助栈、括号匹配、表达式求值、栈模拟队列、区间最值等面试高频题型,每题包含题意、思路、完整代码。
栈核心特性:后进先出LIFO,常用场景:括号校验、递归转迭代、单调性维护、临时缓存。
例题1:有效的括号(基础栈入门)
题目
给定只含()\[\]{}的字符串,判断括号是否有效闭合。
规则:左括号必须同类型右括号闭合;括号必须正确嵌套。
思路
遇左括号入栈;遇右括号,栈顶匹配则出栈,不匹配直接false;最后栈空才合法。
import java.util.Stack;
public boolean isValid(String s) {
Stack stack = new Stack<>();
for(char c : s.toCharArray()){
if(c == '(') stack.push(')');
else if(c == '') stack.push('');
else if(c == '{') stack.push('}');
else {
if(stack.isEmpty() || stack.pop() != c) return false;
}
}
return stack.isEmpty();
}
例题2:用栈实现队列(双栈模拟)
题目
仅使用两个栈实现队列的push、pop、peek、empty操作。
思路
in栈接收入队元素;out栈负责出队,out为空时一次性把in全部倒入out。
import java.util.Stack;
class MyQueue {
Stack in = new Stack<>();
Stack out = new Stack<>();
public void push(int x) {
in.push(x);
}
public int pop() {
in2out();
return out.pop();
}
public int peek() {
in2out();
return out.peek();
}
public boolean empty() {
return in.isEmpty() && out.isEmpty();
}
private void in2out() {
if(out.isEmpty()){
while(!in.isEmpty()) out.push(in.pop());
}
}
}
例题3:最小栈(辅助栈存最小值)
题目
设计栈,支持push、pop、top,额外O(1)获取栈中最小元素。
思路
主栈存元素;辅助栈同步压入当前最小值,出栈时同步弹出。
import java.util.Stack;
class MinStack {
Stack stack = new Stack<>();
Stack minStack = new Stack<>();
public void push(int val) {
stack.push(val);
if(minStack.isEmpty()) minStack.push(val);
else minStack.push(Math.min(val, minStack.peek()));
}
public void pop() {
stack.pop();
minStack.pop();
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
例题4:逆波兰表达式求值(后缀表达式栈计算)
题目
后缀表达式数组,数字直接入栈;运算符弹出两个数计算,结果再入栈。
import java.util.Stack;
public int evalRPN(String\[\] tokens) {
Stack st = new Stack<>();
for(String s : tokens){
if("+".equals(s) || "-".equals(s) || "".equals(s) || "/".equals(s)){
int b = st.pop();
int a = st.pop();
int res;
switch(s){
case "+": res = a+b; break;
case "-": res = a-b; break;
case " ": res = a*b; break;
default: res = a/b;
}
st.push(res);
}else{
st.push(Integer.parseInt(s));
}
}
return st.peek();
}
例题5:字符串解码(嵌套字符串栈缓存)
题目
kencoded_string,把括号内字符串重复k次,支持嵌套,例如3a2\[bc]→abcbcabcbcabcbc。
思路
两个栈:数字栈存倍数,字符串栈存之前拼接好的前缀。
import java.util.Stack;
public String decodeString(String s) {
Stack numSt = new Stack<>();
Stack strSt = new Stack<>();
int num = 0;
StringBuilder curStr = new StringBuilder();
for(char c : s.toCharArray()){
if(Character.isDigit©){
num = num*10 + c-'0';
}else if(c == '['){
numSt.push(num);
strSt.push(curStr.toString());
num = 0;
curStr = new StringBuilder();
}else if(c == ']'){
int cnt = numSt.pop();
StringBuilder tmp = new StringBuilder(strSt.pop());
for(int i=0;i<cnt;i++) tmp.append(curStr);
curStr = tmp;
}else{
curStr.append©;
}
}
return curStr.toString();
}
例题6:柱状图中最大的矩形(单调递增栈经典Hard)
题目
给定高度数组,求柱状图能勾勒出的最大矩形面积。
思路
单调栈存下标,保证对应高度递增;遇到更小高度就弹出计算矩形宽度。
import java.util.Stack;
public int largestRectangleArea(int\[\] heights) {
Stack st = new Stack<>();
int maxArea = 0;
int\[\] arr = new intheights.length+2;
System.arraycopy(heights,0,arr,1,heights.length);
for(int i=0;i<arr.length;i++){
while(!st.isEmpty() && arri < arrst.peek()){
int h = arrst.pop();
int w = i - st.peek() - 1;
maxArea = Math.max(maxArea, h*w);
}
st.push(i);
}
return maxArea;
}
例题7:每日温度(单调递减栈)
题目
温度数组,返回每个位置要等多少天才会出现更高温度,没有填0。
思路
栈存下标,保持栈内温度递减;当前温度大于栈顶,弹出并计算天数差。
import java.util.Stack;
public int\[\] dailyTemperatures(int\[\] temperatures) {
int n = temperatures.length;
int\[\] res = new intn;
Stack st = new Stack<>();
for(int i=0;i<n;i++){
while(!st.isEmpty() && temperaturesi>temperaturesst.peek()){
int idx = st.pop();
residx = i - idx;
}
st.push(i);
}
return res;
}
例题8:删除字符串相邻重复项(栈快速消消乐)
题目
相邻两个相同字符直接删除,反复操作至无可删除,返回最终字符串。
思路
栈顶和当前字符相等则出栈,否则入栈,最后拼接栈内字符。
import java.util.Stack;
public String removeDuplicates(String s) {
Stack st = new Stack<>();
for(char c : s.toCharArray()){
if(!st.isEmpty() && st.peek() == c){
st.pop();
}else{
st.push©;
}
}
StringBuilder sb = new StringBuilder();
while(!st.isEmpty()) sb.append(st.pop());
return sb.reverse().toString();
}
例题9:小行星碰撞(栈模拟碰撞)
题目
整数数组,正数向右、负数向左;大小小的爆炸,相等同时爆炸,同向互不影响。
思路
遍历每个行星,和栈顶向左/向右判断碰撞,循环碰撞直至无冲突。
import java.util.Stack;
public int\[\] asteroidCollision(int\[\] asteroids) {
Stack st = new Stack<>();
for(int ast : asteroids){
boolean alive = true;
while(alive && ast < 0 && !st.isEmpty() && st.peek()>0){
int top = st.peek();
if(top < -ast){
st.pop();
}else if(top == -ast){
st.pop();
alive = false;
}else{
alive = false;
}
}
if(alive) st.push(ast);
}
int\[\] ans = new intst.size();
for(int i=ans.length-1;i>=0;i--) ansi = st.pop();
return ans;
}
例题10:二叉树迭代前序遍历(栈替代递归)
题目
不用递归,用栈实现二叉树前序遍历:根→左→右。
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
class TreeNode{
int val;
TreeNode left,right;
TreeNode(int x){val=x;}
}
public List preorderTraversal(TreeNode root) {
List res = new ArrayList<>();
if(root == null) return res;
Stack st = new Stack<>();
st.push(root);
while(!st.isEmpty()){
TreeNode cur = st.pop();
res.add(cur.val);
if(cur.right != null) st.push(cur.right);
if(cur.left != null) st.push(cur.left);
}
return res;
}
10道栈题型分类汇总
-
基础括号校验:例题1
-
双栈互相模拟:例题2(栈模拟队列)、例题3(最小辅助栈)
-
表达式计算:例题4 逆波兰求值
-
嵌套字符串处理:例题5 字符串解码
-
单调栈(面试高频):例题6 最大矩形、例题7 每日温度
-
相邻字符消除:例题8
-
模拟碰撞逻辑:例题9 小行星碰撞
-
递归转栈迭代:例题10 树遍历