【LeetCode】逆波兰表达式求值Java题解

580 阅读2分钟

这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

题目描述

根据 逆波兰表示法,求表达式的值。

有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

  说明:

整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 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


来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/evaluate-reverse-polish-notation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析

  • 今天的每日一题是栈的应用,这个题目的难点是理解题意,理解题意之后,我们可以从容解决。首先我们明确 逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)。
  • 实现逆波兰式的算法,难度并不大,但为什么要将看似简单的中缀表达式转换为复杂的逆波兰式?原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中序表达式是非常复杂的结构。相对的,逆波兰式在计算机看来却是比较简单易懂的结构。因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。实现代码如下:

通过代码

public class DayCode {
    public static void main(String[] args) {
        String[] s = {"3", "11", "5", "+", "-"};
        int ans = new DayCode().evalRPN(s);
        System.out.println(ans);
    }

    /**
     * 链接:https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/
     * 时间复杂度 O(n)
     * 空间复杂度 O(n)
     * @param tokens
     * @return
     */
    public int evalRPN(String[] tokens) {
        int ans = 0;
        Deque<Integer> stack = new LinkedList<>();
        for (String token : tokens) {
            int temp = 0;
            int num1 = 0;
            int num2 = 0;
            switch (token) {
                case "+":
                    temp = stack.removeLast() + stack.removeLast();
                    stack.addLast(temp);
                    break;
                case "-":
                    num1 = stack.removeLast();
                    num2 = stack.removeLast();
                    stack.addLast(num2 - num1);
                    break;
                case "*":
                    temp = stack.removeLast() * stack.removeLast();
                    stack.addLast(temp);
                    break;
                case "/":
                    num1 = stack.removeLast();
                    num2 = stack.removeLast();
                    stack.addLast(num2 / num1);
                    break;
                default:
                    stack.addLast(Integer.parseInt(token));
                    break;
            }
        }
        if (!stack.isEmpty()) {
            ans = stack.pop();
        }
        return ans;
    }
}

# 总结
* 本题主要利用了栈先入后出的性质,栈还可以用来解决简单计算器等题目。
* 上述算法的时间复杂度是O(n),空间复杂度是O(n)
* 坚持每日一题,加油!