150. 逆波兰表达式求值

中等 含交互动画

学完这道你应该能: 说清它为什么用「栈」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

AI 私教 · 就着本题动画讲
卡住了不用硬扛,按 8 步把这题真正走通。
从读题、试解、找法到手写代码,边问边打勾,适合第一次系统学算法的同学。

题目描述

逆波兰(后缀)表达式的值。运算符写在两个操作数之后,如 “2 1 + 3 *” 表示 (2+1)×3。

tokens = ["2","1","+","3","*"]
输出 = 9

思路解析

直觉是把后缀转回我们熟悉的中缀 (2+1)×3 再算,但要反推括号该加在哪、谁先算,逻辑绕且容易错。难点是运算顺序藏在排列里,没有显式括号告诉你边界。

转折:后缀表达式里「运算符紧跟在它的两个操作数后面」,所以从左到右扫——是数字就压栈先存着;遇到运算符,它要的两个操作数正好是栈顶最近压入的两个,弹出来算完再把结果压回。最近压入的最先被取走,这正是栈。扫完栈里剩的唯一一个数就是答案。

准备 · 栈空:上面是 token 序列,下面是栈。开始逐个 token 处理,栈一开始是空的。

读 2 · 数字入栈:读到数字 2,先存着——压入栈。栈:[2]。

读 1 · 数字入栈:读到数字 1,继续压栈。栈:[2, 1],栈顶是 1。

读 + · 弹两个操作数:读到 +,它要两个操作数。先弹出的 1 是右操作数 b,后弹出的 2 是左操作数 a。顺序很关键:要算的是 a 运算符 b,也就是 2 + 1,不是 1 + 2。

读 + · 结果入栈:算 a + b = 2 + 1 = 3,把结果 3 压回栈。栈变成 [3]。注意这里加法两个数交换无所谓,但若是减法就必须 a−b(2−1),反了就成 1−2 了

读 3 · 数字入栈:读到数字 3,压栈。栈:[3, 3]——下面那个 3 是刚才 2+1 的结果,上面是新读到的 3。

读 * · 弹两个操作数:读到 *,同样弹两个:先弹 b=3(右),再弹 a=3(左)。它俩相乘。

读 * · 结果入栈:算 a × b = 3 × 3 = 9,压回栈。栈:[9]。

结束 · 栈顶即答案:所有 token 读完,栈里只剩一个数 9,它就是整个表达式的值。

后缀表达式没有优先级和括号的烦恼:操作数先存栈、运算符来了就地取最近两个结算。凡是「最近出现的最先被消费」的场景,都该想到栈。

参考代码(Python)

Python
1stack = []
2for tk in tokens:
3    if tk in class="cl-str">"+-*/":
4        b = stack.pop()                  # 先弹的是右操作数
5        a = stack.pop()                  # 后弹的是左操作数
6        if   tk == class="cl-str">"+": stack.append(a + b)
7        elif tk == class="cl-str">"-": stack.append(a - b)     # 必须 a - b
8        elif tk == class="cl-str">"*": stack.append(a * b)
9        else: stack.append(int(a / b))   # 向零取整
10    else: stack.append(int(tk))          # 数字入栈
11return stack[-1]

复杂度分析

  • 时间复杂度:O(n) —— n 个 token 每个只处理一次,进出栈都是 O(1)
  • 空间复杂度:O(n) —— 栈最多同时装约一半个数字

套路模板

记住骨架:操作数入栈、运算符弹两个(下面是左 a、上面是右 b)算完入栈。中缀转后缀、基本计算器都靠它。

Python
1stack = []
2for tk in tokens:
3    if 是操作数(tk): stack.append(转换(tk))
4    else:                                # 是运算符
5        b = stack.pop()                  # 上面 = 右操作数
6        a = stack.pop()                  # 下面 = 左操作数
7        stack.append(运算(a, tk, b))     # 永远 a op b
8return stack[-1]

易错点

  • 错误写法:a、b 顺序搞反,写成 b op a正确写法:b=先弹(右), a=后弹(左), 算 a op b(减法、除法不满足交换律:3 1 - 要算 a−b=3−1=2,反了成 1−3=−2 就错)
  • 错误写法:除法直接用 Python //正确写法:用 int(a / b) 向零取整(题目要求向零取整,而 -7 // 2 = -4,与要求的 -3 不同)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →69. x 的平方根 ← 返回题库