基本计算器的算法实现

248 阅读2分钟

问题描述:

实现一个基本计算器来计算简单的表达式字符串。

表达式字符串可能包含括号和以下运算符: +,-,*,/,和空格 。表达式字符串中的空格字符将被忽略。

您可以假设给定的表达式始终有效。

一些示例:

输入:s = "1 + 1" 输出:2

输入:s = " 6-4 / 2 " 输出:4

输入:s = "2*(5+5*2)/3+(6/2+8)" 输出:21

输入:s = "(2+6* 3+5- (3*14/7+2)*5)+3" 输出:-12

思路:

可以采用递归的方法来解决这个问题。对于当前要计算的表达式,我们需要将它分为两个部分:

  1. 计算没有括号的表达式。
  2. 计算有括号的表达式。

对于没有括号的表达式,我们可以直接从左到右计算。因为乘法和除法的优先级高于加法和减法,所以我们可以使用一个栈来存储数字和运算符。具体来说,我们从左到右扫描字符串,遇到数字时,我们将其压入栈中;遇到运算符时,我们将其与栈顶元素的运算结果压入栈中。

对于有括号的表达式,我们可以使用递归来计算。具体来说,我们先找到最里面的一层括号,然后计算括号内的表达式。我们重复这个过程,直到没有括号为止。

最后,我们需要注意一个细节。当我们遇到一个运算符时,如果栈顶元素为乘法或除法,那么我们需要先将它弹出,并计算运算结果,然后再将当前的运算符压入栈中。

下面是代码实现:

class Solution {
    public int calculate(String s) {
        int num = 0;
        char sign = '+';
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isDigit(c)) {
                num = num * 10 + (c - '0');
            }
            if (c == '(') {
                int[] res = helper(s, i + 1);
                num = res[0];
                i = res[1];
            }
            if ((!Character.isDigit(c) && c != ' ') || i == s.length() - 1) {
                if (sign == '+') {
                    stack.push(num);
                } else if (sign == '-') {
                    stack.push(-num);
                } else if (sign == '*') {
                    stack.push(stack.pop() * num);
                } else {
                    stack.push(stack.pop() / num);
                }
                num = 0;
                sign = c;
            }
            if (c == ')') {
                break;
            }
        }
        int res = 0;
        while (!stack.isEmpty()) {
            res += stack.pop();
        }
        return res;
    }
    
    private int[] helper(String s, int i) {
        int num = 0;
        char sign = '+';
        Stack<Integer> stack = new Stack<>();
        while (i < s.length()) {
            char c = s.charAt(i);
            if (Character.isDigit(c)) {
                num = num * 10 + (c - '0');
            }
            if (c == '(') {
                int[] res = helper(s, i + 1);
                num = res[0];
                i = res[1];
            }
            if ((!Character.isDigit(c) && c != ' ') || i == s.length() - 1) {
                if (sign == '+') {
                    stack.push(num);
                } else if (sign == '-') {
                    stack.push(-num);
                } else if (sign == '*') {
                    stack.push(stack.pop() * num);
                } else {
                    stack.push(stack.pop() / num);
                }
                num = 0;
                sign = c;
            }
            if (c == ')') {
                break;
            }
            i++;
        }
        int res = 0;
        while (!stack.isEmpty()) {
            res += stack.pop();
        }
        return new int[]{res, i};
    }
}