Link: https://leetcode.cn/problems/basic-calculator/

Question

difficulty: hard
adj diff: 5

Given a string s representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation.

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().

 

Example 1:

Input: s = "1 + 1"
Output: 2

Example 2:

Input: s = " 2-1 + 2 "
Output: 3

Example 3:

Input: s = "(1+(4+5+2)-3)+(6+8)"
Output: 23

 

Constraints:

    1 <= s.length <= 3 * 105
    s consists of digits, '+', '-', '(', ')', and ' '.
    s represents a valid expression.
    '+' is not used as a unary operation (i.e., "+1" and "+(2 + 3)" is invalid).
    '-' could be used as a unary operation (i.e., "-1" and "-(2 + 3)" is valid).
    There will be no two consecutive operators in the input.
    Every number and running calculation will fit in a signed 32-bit integer.

Too hard. 太难了,不会写。

2条Stack,一个存 number,一个存operator。看代码吧。

Code

Solution reference: https://leetcode.cn/problems/basic-calculator/solution/shuang-zhan-jie-jue-tong-yong-biao-da-sh-olym/

class Solution {

    Stack<Integer> numbers = new Stack<Integer>();
    Stack<Character> operators = new Stack<Character>();

    public int calculate(String s) {
        numbers.push(0);
        char[] expression = s.replace(" ", "").toCharArray();

        for (int i = 0; i < expression.length; i++) {
            char ch = expression[i];
            if (ch == '(') {
                operators.push(ch);
            } else if (ch == ')') {
                while (!operators.isEmpty()) {
                    // 计算到最近一个左括号为止
                    if (operators.peek() == '(') {
                        operators.pop();
                        break;
                    } else {
                        calculateOnce();
                    }
                }
            } else if ('0' <= ch && ch <= '9') {
                int u = 0;
                int j = i;
                // 将从 i 位置开始后面的连续数字整体取出,加入 numbers
                while (j < expression.length 
                        && ('0' <= expression[j] && expression[j] <= '9')
                    ) {
                    u = u * 10 + (int)(expression[j++] - '0');
                }
                numbers.push(u);
                i = j - 1;
            } else { // is an operator, namely: + or -
                if (i > 0 
                    && (expression[i - 1] == '(' 
                        || expression[i - 1] == '+' 
                        || expression[i - 1] == '-')
                    ) {
                    numbers.push(0);
                }
                // 有一个新操作要入栈时,先把栈内可以算的都算了
                while (!operators.isEmpty() && operators.peek() != '(') {
                    calculateOnce();
                }
                operators.push(ch);
            }
        }

        while (!operators.isEmpty()) {
            calculateOnce();
        }
        return numbers.peek();
    }

    private void calculateOnce() {
        if (numbers.isEmpty() || numbers.size() < 2) return;
        if (operators.isEmpty()) return;
        int b = numbers.pop(), a = numbers.pop();
        char op = operators.pop();
        numbers.push(op == '+' ? a + b : a - b);
    }
}