772. Basic-Calculator-III

difficulty: Hard

section pre{ background-color: #eee; border: 1px solid #ddd; padding:10px; border-radius: 5px; }

Implement a basic calculator to evaluate a simple expression string.

The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .

The expression string contains only non-negative integers, +, -, *, / operators , open ( and closing parentheses ) and empty spaces . The integer division should truncate toward zero.

You may assume that the given expression is always valid. All intermediate results will be in the range of [-2147483648, 2147483647].

Some examples:

"1 + 1" = 2
" 6-4 / 2 " = 4
"2*(5+5*2)/3+(6/2+8)" = 21
"(2+6* 3+5- (3*14/7+2)*5)+3"=-12

Note: Do not use the eval built-in library function.

Method One

class Solution {
    public int calculate(String s) {
       Queue<Character> tokens = new ArrayDeque<Character>();

       for(char c : s.toCharArray()){
           if(c != ' ') tokens.offer(c);
       }

       tokens.offer('t'); // offer dummyTail 让最后一个字符也能被处理
       return calculate(tokens);
    }

    private int calculate(Queue<Character> tokens){
        /** 
        有三类字符,1是数字,2是括号,3是运算符。
        对字符串处理,我们的 notations 是这样的: sum +  preNum preOp num  c,
        sum 就是之前所有运算的结果, preNum preOp num 是我们最近邻的一个完整的表达式, c 是我们目前处理的字符。
        如果我们碰到的 c 是数字,说明我们需要更新 num.
        如果 c 是左括号,说明 c 前面是 preOp, 我们开始 dfs 直到 右括号结束,我们把整个括号内的结果作为num.
        如果 c 是右括号,意味着运算终止,此时我们要先处理 sum +  preNum preOp num 再打断循环并向上返回结果。
        如果 c 是一个运算符,那么我们也要立刻处理 sum +  preNum preOp num
            如果 preOp 是 +,-, => sum = sum +  preNum; preNum = +,- num; preOp = c.
            如果 preOp 是 *,/, => sum = sum; preNum = preNum *,/ num; preOp = c.
        因此运算结束的时候,我们会始终保留一个 sum + preNum, 因此需要返回 sum + preNum. 
        */
        int sum = 0;
        int preNum = 0;
        char preOp = '+';
        int num = 0;
        while(!tokens.isEmpty()) {
            char c = tokens.poll();

            if('0' <= c && c <= '9') {
                num = num * 10 + ( c - '0' );
            }else if( c == '(' ) {
                num = calculate(tokens);
            }else {
                switch (preOp){
                    case '+':
                        sum += preNum;
                        preNum = num;
                        break;
                    case '-':
                        sum += preNum;
                        preNum = -num;
                        break;
                    case '*':
                        preNum *= num;
                        break;
                    case '/':
                        preNum /= num;
                        break;
                }

                if( c == ')' ) {
                    break;
                }
                preOp = c;
                num = 0;
            }
       }

       return sum + preNum;
    }
}

Last updated

Was this helpful?