LeetCode 224, 227, 772. Basic Calculator I+II+III

Basic Calculator

由于只需要实现加减和括号,除了括号不需要考虑运算的优先级,所以可以直接one pass做。

思路是将 a-b 等价为 a+(-b),这样所有的运算都是加法,而负号只要乘以后面的数即可。

建立一个stack,遇到左括号时,压栈迄今为止的和以及括号前的符号。遇到对应右括号时,括号内已经计算完毕,这时我们将括号内计算得到的sum*栈顶的符号,再加上栈内前面部分的和即可。

class Solution {
public:
    int calculate(string s) {
        // a-b <=> a+(-b)
        int res=0, sign=1;
        stack<int> st;
        
        for (int i=0;i<s.size();++i){
            char ch=s[i];
            if (isdigit(ch)){
                int num=0;
                while (i<s.size() && isdigit(s[i])){
                    num = num*10 + (s[i++]-'0');
                }
                --i;
                res += sign*num;
            }else if (ch=='+' || ch=='-'){
                sign = ch=='+'?1:-1;
            }else if (ch=='('){
                st.push(res);
                st.push(sign);
                res = 0;
                sign = 1;
            }else if (ch==')'){
                res *= st.top(); st.pop();
                res += st.top(); st.pop();
            }
        }
        return res;
    }
};

 

Basic Calculator II

四则运算没有括号,有空格。四则运算就算有括号,用两个stack,其中opstack保证优先级严格单增即可。

discuss 里有很多不用stack的方法,记录之前的符号,读到数字时再根据前面符号处理。个人觉得容易写错,还是标准两个stack比较好,扩展性也更强。

 class Solution {
public:
    unordered_map<char,int> pri{{'+',1},{'-',1},{'*',2},{'/',2}};
    
    int calculate(string s) {
        int res=0;
        stack<int> numStack;
        stack<char> opStack;
        
        for (int i=0;i<s.size();++i){
            char ch=s[i];
            if (ch==' ') continue;
            if (isdigit(ch)){
                int num=0;
                while (i<s.size() && isdigit(s[i])){
                    num = num*10 + (s[i++]-'0');
                }
                --i;
                numStack.push(num);
            }else{ // operand
                char op=s[i];
                while (!opStack.empty() && pri[opStack.top()]>=pri[op]){
                    calc(numStack,opStack);
                }
                opStack.push(op);
            }
        }
        
        while (!opStack.empty()){
            calc(numStack,opStack);
        }
        return numStack.top();
    }
    
    void calc(stack<int> &numStack, stack<char> &opStack){
        char op=opStack.top(); opStack.pop();
        int num1=numStack.top(); numStack.pop();
        int num2=numStack.top(); numStack.pop();
        if (op=='+') numStack.push(num2+num1);
        else if (op=='-') numStack.push(num2-num1);
        else if (op=='*') numStack.push(num2*num1);
        else if (op=='/') numStack.push(num2/num1);
    }
};

 

Basic Calculator III

上一题的followup,存在括号的四则运算。左括号优先级最低,遇到右括号需要一直 calc 直到opStack遇到左括号终止。别的运算比如乘方也可以拓展。

class Solution {
public:
    unordered_map<char,int> pri{{'(',0},{'+',1},{'-',1},{'*',2},{'/',2}};
    
    int calculate(string s) {
        int res=0;
        stack<int> numStack;
        stack<char> opStack;
        
        for (int i=0;i<s.size();++i){
            char ch=s[i];
            if (ch==' ') continue;
            if (isdigit(ch)){
                int num=0;
                while (i<s.size() && isdigit(s[i]))
                    num = num*10 + (s[i++]-'0');
                --i;
                numStack.push(num);
            }else { // operand
                char op=s[i];
                if (op=='(') opStack.push(op);
                else if (op==')'){
                    while (!opStack.empty() && opStack.top()!='(')
                        calc(numStack,opStack);
                    opStack.pop(); // pop '('    
                }else{
                    while (!opStack.empty() && pri[opStack.top()]>=pri[op])
                        calc(numStack,opStack);
                    opStack.push(op);
                }
            }
        }
        
        while (!opStack.empty()){
            calc(numStack,opStack);
        }
        return numStack.top();
    }
    
    void calc(stack<int> &numStack, stack<char> &opStack){
        char op=opStack.top(); opStack.pop();
        int num1=numStack.top(); numStack.pop();
        int num2=numStack.top(); numStack.pop();
        if (op=='+') numStack.push(num2+num1);
        else if (op=='-') numStack.push(num2-num1);
        else if (op=='*') numStack.push(num2*num1);
        else if (op=='/') numStack.push(num2/num1);
    }
};

 

转载于:https://www.cnblogs.com/hankunyan/p/11276993.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值