Medium草稿★★★★O(n) 時間 · O(n) 空間
StackMath
Patterns🥞 堆疊🧮 數學・組合
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

150Evaluate Reverse Polish NotationStackMediumStack

給定一個字串陣列 tokens 代表逆波蘭表示法 (RPN) 的算術運算式,計算並回傳結果。有效運算子為 +-*/,除法向零截斷。

Example:

Input: tokens = [“2”,“1”,”+”,“3”,”*”] Output: 9 (即 (2 + 1) * 3)

Intuition

TIP

核心思路:RPN 的求值天然適合用堆疊——遇到數字壓入,遇到運算子彈出兩個數計算後壓回。

Approaches

1. Recursion (Reverse Parse) — O(n) / O(n)
  • Idea: 從 tokens 末尾開始,遇到運算子就遞迴求左右子樹;遇到數字就直接回傳
  • Time: O(n) - 每個 token 處理一次
  • Space: O(n) - 遞迴深度
class Solution {
    private var index = 0

    fun evalRPN(tokens: Array<String>): Int {
        index = tokens.size - 1
        return evaluate(tokens)
    }

    private fun evaluate(tokens: Array<String>): Int {
        val token = tokens[index--]
        if (token !in setOf("+", "-", "*", "/")) {
            return token.toInt()
        }
        val right = evaluate(tokens)
        val left = evaluate(tokens)
        return when (token) {
            "+" -> left + right
            "-" -> left - right
            "*" -> left * right
            "/" -> left / right
            else -> throw IllegalArgumentException()
        }
    }
}
⭐ 2. Stack — O(n) / O(n)
  • Idea: 遍歷 tokens,數字壓入堆疊,遇到運算子彈出兩個數計算後將結果壓回
  • Time: O(n) - 遍歷一次 tokens
  • Space: O(n) - 堆疊最多存 n/2 個數
class Solution {
    fun evalRPN(tokens: Array<String>): Int {
        val stack = ArrayDeque<Int>()

        for (token in tokens) {
            when (token) {
                "+", "-", "*", "/" -> {
                    val b = stack.removeLast()
                    val a = stack.removeLast()
                    val result = when (token) {
                        "+" -> a + b
                        "-" -> a - b
                        "*" -> a * b
                        "/" -> a / b
                        else -> throw IllegalArgumentException()
                    }
                    stack.addLast(result)
                }
                else -> stack.addLast(token.toInt())
                }
        }

        return stack.last()
    }
}

WARNING

注意彈出順序:先彈出的是右運算元 b,後彈出的是左運算元 aa - ba / b 的順序弄反會得到錯誤結果。Kotlin 的 Int 除法預設就是向零截斷,符合題意。

🔑 Takeaways