逆波兰表达式求值&计算器

逆波兰表达式求值

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

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

说明:

  • 整数除法只保留整数部分。
  • 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:

输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:

输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

示例 3:

输入: ["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 + 2 ) * ( 3 + 4 )
  • 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * )

逆波兰表达式主要有以下两个优点:

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + *也可以依据次序计算出正确结果。
  • 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

依次运算即可

public int evalRPN(String[] tokens) {
    Stack stack = new Stack<>();
    for (int i = 0; i < tokens.length; i++) {
        String s = tokens[i];
        switch (s) {
            case "+":
                stack.push(stack.pop() + stack.pop());
                break;
            case "-":
                stack.push(-stack.pop() + stack.pop());
                break;
            case "*":
                stack.push(stack.pop() * stack.pop());
                break;
            case "/":
                Integer num = stack.pop();
                stack.push(stack.pop() / num);
                break;
            default:
                stack.push(Integer.parseInt(s));
        }
    }
    return stack.pop();
}

计算器

给定一个包含正整数、加(+)、减(-)、乘(*)、除(/)的算数表达式(括号除外),计算其结果。

表达式仅包含非负整数,+-*/ 四种运算符和空格 。 整数除法仅保留整数部分。

示例 1:

输入: "3+2*2"
输出: 7

示例 2:

输入: " 3/2 "
输出: 1

示例 3:

输入: " 3+5 / 2 "

输出: 5

private Map map = new HashMap<>();

{
    map.put('/', 2);
    map.put('*', 2);
    map.put('-', 1);
    map.put('+', 1);
}

public int calculate(String s) {
    Stack numStack = new Stack<>();
    Stack operatorStack = new Stack<>();
    for (int i = 0; i < s.length();) {
        char c = s.charAt(i);
        if (!isNumber(c)) {//不是数字
            if (c != ' ') {//考虑空格
                boolean flag = false;
                //while考虑2-3/4+1,计算完3/4=0后,要先计算2-0
                while (!operatorStack.isEmpty() && isPrior(operatorStack.peek(), c)) {
                    calculate(numStack, operatorStack);
                    flag = true;
                }
                if (flag) {
                    operatorStack.push(s.charAt(i));
                } else {
                    operatorStack.push(c);
                }
            }
            i++;
        } else {
            StringBuilder sb = new StringBuilder();
            while (i < s.length() && isNumber(s.charAt(i))) {//多位数字
                sb.append(s.charAt(i));
                i++;
            }
            numStack.push(Integer.parseInt(sb.toString()));
        }
    }
    while (!operatorStack.isEmpty()) {
        calculate(numStack, operatorStack);
    }
    return numStack.pop();
}

private int calculate(int num1, int num2, char c) {
    if (c == '+') {
        return num1 + num2;
    }
    if (c == '-') {
        return num1 - num2;
    }
    if (c == '*') {
        return num1 * num2;
    }
    return num1 / num2;
}

public void calculate(Stack numStack, Stack opStack) {
    char op = opStack.pop();
    int num1 = numStack.pop();
    int num2 = numStack.pop();
    numStack.push(calculate(num2, num1, op));
}

private boolean isNumber(char c) {
    return c >= '0' && c <= '9';
}

private boolean isPrior(char c1, char c2) {
    return map.get(c1) >= map.get(c2);
}
`

你可能感兴趣的:(逆波兰表达式求值&计算器)