150. 逆波兰表达式求值

150. 逆波兰表达式求值

✨核心逻辑

本题采用 栈(Stack) 的处理策略:

  1. 遇数入栈:遍历整个字符串数组,如果遇到的是数字,将其转换为 int 类型后直接压入栈中。
  2. 遇符出栈:如果遇到的是运算符,则从栈顶弹出两个数字(即当前运算符所需要的两个操作数)。
  3. 注意顺序:由于栈是后进先出的结构,先弹出的数字 pop1 其实是表达式中的“右侧操作数”,后弹出的数字 pop2 是“左侧操作数”。因此,对于减法和除法,要特别注意顺序:执行 pop2 - pop1pop2 / pop1
  4. 结果入栈:将计算得到的结果重新压入栈中,供后续的运算使用。
  5. 返回结果:当所有元素遍历处理完毕后,栈中唯一的数字就是这个算术表达式的最终结果。

🔥代码实现(含详细变量注释)

class Solution {
    public int evalRPN(String[] tokens) {
        // 边界情况:如果表达式只有一个数字,直接将其转换并返回
        if (tokens.length == 1) {
            return Integer.valueOf(tokens[0]);
        }
        
        // deque:使用双端队列来模拟栈结构,比旧版 Stack 类性能更好
        Deque<Integer> deque = new ArrayDeque<>();
        // result:用于记录当前运算符计算出来的临时结果
        int result = 0;
        
        // st:遍历指针,依次读取字符串数组中的每一个字符元素(可能是数字,也可能是运算符)
        for (String st : tokens) {
            // 如果当前字符串是运算符
            if (st.equals("+") || st.equals("-") || st.equals("*") || st.equals("/")) {
                // pop1:栈顶元素,是当前运算符的右侧操作数(先弹出的数)
                int pop1 = Integer.valueOf(deque.pop());
                // pop2:次栈顶元素,是当前运算符的左侧操作数(后弹出的数)
                int pop2 = Integer.valueOf(deque.pop());
                
                // 根据不同的运算符执行不同的数学运算
                if (st.equals("+")) {
                    result = pop1 + pop2;
                }
                if (st.equals("-")) {
                    // 注意:减法必须用“左侧操作数 - 右侧操作数”
                    result = pop2 - pop1;
                }
                if (st.equals("*")) {
                    result = pop1 * pop2;
                }
                if (st.equals("/")) {
                    // 注意:除法必须用“左侧操作数 / 右侧操作数”(题目保证不会除零)
                    result = pop2 / pop1;
                }
                // 将本次计算的结果重新压入栈中,作为下一步运算的数据
                deque.push(result);
            } else {
                // 如果当前字符串不是运算符,说明是操作数(数字)
                // 将其转换为 int 后直接压入栈中
                deque.push(Integer.valueOf(st));
            }
        }
        // 遍历结束后,栈中剩下的最后一个数字即为表达式最终计算结果
        return result;
    }
}


  • ⏱️复杂度分析
    • 时间复杂度:O(N),其中 N 是逆波兰表达式数组 tokens 的长度。我们只需要对数组进行一次遍历,遍历过程只涉及常数次的栈弹出和压入操作。

    • 空间复杂度:O(N),最坏情况下,表达式中全都是数字没有运算符,此时栈的大小会达到 N,用于存储所有中间结果和操作数。