224. Basic Calculator

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 .
Input: “(1+(4+5+2)-3)+(6+8)”
Output: 23

hard难度的题,其实观察发现hard的题往往最初思路的构造并不难,难在实现过程中会有很多的情况需要考虑;
这道题思路其实是很好寻找的,表达式中括号内部必然也是一个完整的算式,所以很容易想到使用递归的思路去解决,对于每一个括号我们将括号内部的字符串作为新的参数进行调用,就可以将一对括号的表达式转化成一个具体的数值。
细节上有一点点复杂,为了方便首先先采用 str.replaceAll(” “,”“)将空格去掉,那么我们只剩下三种可能:
1.’(’ :这就标志着一次递归调用的开始,我们发现一次递归调用必然是以一个括号开始一个括号结束的,那么我们可以将参数设计成开始的index,在每次扫描到’(‘时候发起新的调用,然后调用完成之后将i变成子调用结束之后的位置;
2.’)’标志着当前调用层的结束
3.’数字’,加入到cur当前的数字值中
4.’符号’,意味着上一个符号+数字的组合已经完成,所以将结果进行计算,并且重新初始化符号和数值

//递归版本
class Solution {
    char[] a;
    String s;
    public int calculate(String str) {
        s = str.replaceAll(" ","");
        a = s.toCharArray();
        return cal(0)[0];
    }

    public int[] cal(int s){
        int res = 0;
        int cur = 0;
        int sign = 1;
        int[] data = new int[2];
        for(int i = s;;i++){
            if(i>=a.length || a[i] == ')'){
                res += cur * sign;
                data[0] = res;
                data[1] = i;
                return data;
            }
            if(a[i] == '+' || a[i] =='-'){
                res += sign * cur;
                cur = 0;
                sign = a[i]=='+'? 1:-1;
            }
            else if(a[i]=='('){
                int[] part = cal(i+1);
                i = part[1];
                res+=sign*part[0];
            }
            else{
                cur = cur*10 + (a[i]-'0');
            }
        }
    }
}

因为递归调用本质上是用jvm的栈来存储调用顺序的,所以我们自然可以自己手动用栈来实现计算,整体思路与上面类似,在遇到一个(的时候意味着我们需要进入更高一级的表达式,用栈存储当前级的计算结果和符号,进行下一级的运算;在遇到‘)’的时候就意味着我们这一级已经完成了,将该级的结果与栈顶的上一级结果进行合成;

class Solution {
    public int calculate(String s) {
        s = s.replaceAll(" ","");
        int layer = 0;
        int num = 0;
        int sign = 1;
        char[] a = s.toCharArray();
        Stack<Integer> stack = new Stack<>();
        for(char c:a){
            if(c=='('){
            \\进入新的一层,将当前层的现场放入栈中保留
                stack.push(layer);
                stack.push(sign);
                sign = 1;
                layer = 0;
            }
            else if(c=='+' || c=='-'){
                layer += num * sign;
                num = 0;
                sign = c=='+'? 1:-1;
            }
            else if(c==')'){
            \\当前层结束,返回之前的层;
                layer += num * sign;
                num = 0;
                layer = layer * stack.pop() + stack.pop();
            }
            else num = num*10 + (c-'0');
        }
        **\\注意这一步很关键,对于单层没有右括号的情况,最后一项并不会在循环中进行运算**
        return layer+num*sign;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_24436311/article/details/81432298