题目描述
思路解析动画文字版
逆波兰本来就是为栈设计的。没必要先补括号,再解析表达式树。
遇到数字先放着。遇到运算符,弹出右操作数 b,再弹出左操作数 a,算完结果压回栈。
读到 2:数字 2 入栈,等待后面的运算符。
读到 1:数字 1 入栈。现在栈顶两个数是 2 和 1。
读到 + · 弹右操作数:遇到加号。栈顶 1 是最近入栈的,先把它弹出来当右操作数 b。
读到 + · 弹左操作数并计算:1 已经出栈。再弹出栈顶 2 当左操作数 a,计算 a+b = 2+1 = 3。
读到 + · 结果压回:把结果 3 压回栈。两个数变成一个数——这就是一次运算的净效果。
读到 3:数字 3 入栈。栈里现在是上一轮结果 3 和新数字 3。
读到 * · 弹右操作数:遇到乘号。先弹出栈顶的 3 当右操作数 b。
读到 * · 弹左操作数并计算:右操作数 3 已出栈。再弹出最后的 3 当左操作数 a,计算 a*b = 3*3 = 9,此刻栈空。
读到 * · 结果压回:把结果 9 压回栈。
结束:所有 token 扫完,栈里唯一的数就是答案。
注意弹出顺序:先弹的是右操作数 b。
边界三连:单数字、负数、除法,都能测出栈处理是否严谨。
雷区实演 · 减法先弹右操作数:tokens=["4","2","-"]。遇到减号,栈顶的 2 是最近入栈的,先被弹出当右操作数 b。
雷区实演 · 减法再弹左操作数:2 已出栈。再弹出 4 当左操作数 a,计算 a-b = 4-2 = 2,不是 2-4。先弹的是右操作数,顺序千万别反。
面试追问 1:运算符总是消费最近的两个尚未合并的操作数,正好符合后进先出。
面试追问 2:不同语言对负数整数除法细节不同,题目要求向 0 截断。
面试追问 3:LeetCode 通常保证合法;生产场景要检查栈数量和 token。
这题学完不要乱跳,下一步去 栈专题 连刷同类题;卡住时用 AI 答疑追问“为什么这一步成立”,比只背答案更稳。
参考代码
class Solution: def evalRPN(self, tokens): st = [] for t in tokens: if t not in '+-*/': # 子串判断,靠 LC 保证 token 非空 st.append(int(t)) else: b = st.pop() a = st.pop() if t == '+': st.append(a + b) elif t == '-': st.append(a - b) elif t == '*': st.append(a * b) else: st.append(int(a / b)) return st[-1]复杂度
- 时间复杂度:O(n),每个 token 只处理一次
- 空间复杂度:O(n),最坏全是数字先入栈
可套用的代码模板
这个骨架是「后缀表达式求值」的通用形:操作数先攒进栈,遇二元运算符就恰好弹 2 个(先弹的是右操作数)、算完压回。注意它不是单调栈的「while 反复结算栈顶」——RPN 每个运算符固定结算两个数。换题(如含括号的中缀计算器)时,只要替换 isOperand/apply,框架不变。
# 表达式求值骨架:操作数攒着,遇运算符就「定量结算」st = []for tok in tokens: if 是操作数(tok): st.append(转成数(tok)) # 先攒着,等运算符 else: # 二元运算符:恰好弹 2 个 b = st.pop() # 先弹 = 右操作数 a = st.pop() # 后弹 = 左操作数 st.append(apply(tok, a, b)) # a op b 压回return st[-1] # 合法表达式只剩 1 个易错点
面试追问把动画讲成自己的话
追问为什么逆波兰适合栈?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
括号生成
LeetCode 22 · 中等 · 沿着 栈 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题