AlgoMooc
你已开通华为OD训练营权益,还差最后一步——完成入营激活(兑换课程 + 加飞书 + 登记服务群),即可解锁全部课程与专属服务。去激活 →
← OD 20 天课程

华为 OD 训练营 · 题解精讲

LC150. 逆波兰表达式求值

LC150. 逆波兰表达式求值 预习和复习可以查看我的讲解视频。

题目描述

根据 逆波兰表示法,求表达式的值。 有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 注意 两个整数之间的除法只保留整数部分,向零截断。 可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 示例 1: 输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9 示例 2: 输入:tokens = ["4","13","5","/","+"] 输出:6 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6 示例 3: 输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"] 输出:22 解释:该算式转化为常见的中缀算术表达式为: ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 = ((10 * (6 / (12 * -11))) + 17) + 5 = ((10 * (6 / -132)) + 17) + 5 = ((10 * 0) + 17) + 5 = (0 + 17) + 5 = 17 + 5 = 22 提示: 1 <= tokens.length <= 10^4 tokens[i] 是一个算符("+"、"-"、"*" 或 "/"),或是在范围 [-200, 200] 内的一个整数 逆波兰表达式: 逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。 逆波兰表达式主要有以下两个优点: 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + *也可以依据次序计算出正确结果。 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中

题目解析

解题思路

逆波兰表达式(后缀表达式)天然适合用栈求值。核心规则:遇到数字入栈,遇到运算符则弹出栈顶两个数字计算,结果再压回栈。遍历结束后栈中唯一元素即为表达式结果。

数据结构:使用 Python 列表模拟栈(result 作为栈)。

关键点

  • 运算符弹出顺序:先弹出的是右操作数rightNum),后弹出的是左操作数leftNum),因为栈是后进先出。
  • 除法向零截断:使用 int(leftNum / rightNum) 实现(Python 的 // 对负数会向下取整,不符合题意,因此用 int() 截断小数部分)。

关键步骤

1. 初始化空栈 result = []。 2. 遍历 tokens

  • 若当前 token 是运算符:
  • 弹出 rightNum = result.pop()
  • 弹出 leftNum = result.pop()
  • 根据运算符计算 ans
  • 否则(数字字符串):ans = int(token)
  • ans 压入栈 result.append(ans)

3. 返回栈顶 result[-1]

["2","1","+","3","*"] 为例的栈变化:


初始: []
读 "2": [2]
读 "1": [2, 1]
读 "+": 弹出 122+1=3 → [3]
读 "3": [3, 3]
读 "*": 弹出 333*3=9 → [9]
返回 9

复杂度分析

  • 时间复杂度:O(n),其中 n 为 tokens 长度。每个 token 只处理一次,栈操作 O(1)。
  • 空间复杂度:O(n),最坏情况下所有 token 都是数字(如 ["1","2","3","4","5"]),栈需存储所有数字。

参考代码

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        # 使用一个列表作为栈,存储操作数,从左到右遍历逆波兰表达式
        result = []

        # 遍历字符串数组
        for token in tokens:
            # 如果是运算符
            if token in "+-*/":
                # 先出栈的是右操作数
                rightNum = result.pop()
                # 后出栈的是左操作数
                leftNum = result.pop()
                # 计算结果
                if token == "+":
                    ans = leftNum + rightNum
                elif token == "-":
                    ans = leftNum - rightNum
                elif token == "*":
                    ans = leftNum * rightNum
                elif token == "/":
                    ans = int(leftNum / rightNum)
            else:
                # 转换为数字
                ans = int(token)

            # 存储结果
            result.append(ans)

        # 返回栈顶元素
        return result[-1]