【LeetCode】150. 逆波兰表达式求值

leetcode

 

实现思路

  1. 栈结构:利用切片模拟栈,存储运算过程中的中间结果。
  2. 操作符处理:遇到运算符时,从栈顶弹出两个操作数,按运算符计算后将结果重新压栈。
  3. 运算顺序:注意减法和除法中操作数的顺序(第二个弹出的数是左操作数,第一个是右操作数)。
  4. 整数除法:Golang 默认的整数除法已实现向零截断,直接使用即可。
func evalRPN(tokens []string) int {
    stack := []int{}
    operators := map[string]bool{"+": true, "-": true, "*": true, "/": true}

    for _, token := range tokens {
        if _, ok := operators[token]; ok {
            // 弹出右操作数和左操作数
            right := stack[len(stack)-1]
            left := stack[len(stack)-2]
            stack = stack[:len(stack)-2]

            // 执行运算
            var res int
            switch token {
            case "+":
                res = left + right
            case "-":
                res = left - right
            case "*":
                res = left * right
            case "/":
                res = left / right
            }
            stack = append(stack, res)
        } else {
            // 数字入栈
            num, _ := strconv.Atoi(token)
            stack = append(stack, num)
        }
    }
    return stack[0]
}

核心逻辑解析

  1. 栈操作

    • 压栈:遇到数字时通过 strconv.Atoi 转换后存入切片。
    • 弹栈:遇到运算符时弹出栈顶两个元素,按优先级处理后重新压栈。
  2. 运算顺序控制

    right := stack[len(stack)-1]  // 右操作数(后入栈)
    left := stack[len(stack)-2]   // 左操作数(先入栈)

    例如对表达式 ["4","13","5","/","+"]

    • 先计算 13/5=2(右操作数 5,左操作数 13)。
    • 再计算 4+2=6(右操作数 2,左操作数 4)。
  3. 边界处理

    • 题目保证输入有效,无需处理非法运算符或空栈情况。
    • 最终栈中仅剩一个元素即为结果。

复杂度分析

指标说明
时间复杂度 O(n) 遍历所有 token 一次
空间复杂度 O(n) 栈最多存储 n/2+1 个元素

示例验证

func main() {
    fmt.Println(evalRPN([]string{"2","1","+","3","*"}))    // 输出 9
    fmt.Println(evalRPN([]string{"4","13","5","/","+"}))    // 输出 6
    fmt.Println(evalRPN([]string{"10","6","9","3","+","-11","*","/","*","17","+","5","+"})) // 输出 22
}

算法优势

  1. 无歧义性:无需处理运算符优先级和括号,直接按顺序计算。
  2. 高效性:单次遍历即可完成计算,时间复杂度最优。
  3. 低内存占用:栈空间仅存储中间结果,内存使用与表达式复杂度线性相关。
posted @ 2025-03-30 15:45  云隙之间  阅读(33)  评论(0)    收藏  举报