LeetCode 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 .

You may assume that the given expression is always valid.

Some examples:

"1 + 1" = 2
" 2-1 + 2 " = 3
"(1+(4+5+2)-3)+(6+8)" = 23

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

先用最通用的(转换为后缀表达式,然后对后缀表达式求值):

class Solution {
public:
    int calculate(string s) {
        vector<long> postfix = to_postfix(s);
        int len = postfix.size();
        if (len == 0) {
            return 0;
        }
        vector<long> tmp;
        long a, b;
        for (int i=0; i<len; i++) {
            long ch = postfix[i];
            switch(ch) {
                case '+':
                    a = tmp.back();
                    tmp.pop_back();
                    tmp.back() = tmp.back() + a;
                    break;
                case '-':
                    a = tmp.back();
                    tmp.pop_back();
                    tmp.back() = tmp.back() - a;
                    break;
                default:
                    tmp.push_back(-ch);
            }
        }
        return tmp[0];
    }
    
    vector<long> to_postfix(const string& s) {
        int len = s.size();
        // operators
        vector<char> operato;
        // generated postfix experssion of this infix experssion
        vector<long> postfix;
        
        int val = 0;
        bool innum = false;
        
        for (int i=0; i<len; i++) {
            char ch = s[i];
            switch (ch) {
                case ' ':
                    // skip space
                    continue;
                case '-':
                case '+':
                    while (!operato.empty() && operato.back() != '(') {
                        postfix.push_back(operato.back());
                        operato.pop_back();
                    }
                    operato.push_back(ch);
                    break;
                case '(':
                    // just push to operato
                    operato.push_back(ch);
                    break;
                case ')':
                    // move any operato between this ')' and it's paired '('
                    while (!operato.empty() && operato.back() != '(') {
                        postfix.push_back(operato.back());
                        operato.pop_back();
                    }
                    // destroy '(' placeholder
                    operato.pop_back();
                    break;
                default:
                    if (innum) {
                        val = val * 10 + ch - '0';
                    } else {
                        val = ch - '0';
                        innum = true;
                    }
                    // look ahead
                    if (i+1 == len || s[i+1] > '9' || s[i+1] < '0') {
                        postfix.push_back(-val);
                        innum = false;
                    }
            }
        }
        
        while (!operato.empty()) {
            postfix.push_back(operato.back());
            operato.pop_back();
        }
        return postfix;
    }
};

 下面这个用递归的方式处理每个括号中的表达式,但是MLE

class Solution {
public:
    int calculate(string s) {
        int len = s.size();
        int val = 0;
        char lastop = '+';
        for (int i=0; i<len; i++) {
            char ch = s[i];
            switch(ch) {
                case ' ':
                    break;
                case '(':{
                    int cnt = 1;
                    int idx = ++i;
                    while (cnt != 0) {
                        if (s[i] == '(') {
                            cnt++;
                        } else if (s[i] == ')') {
                            cnt--;
                        }
                        i++;
                    }
                    i--;
                    int t = calculate(s.substr(idx, i - idx));
                    val = lastop == '-' ? (val - t) : (val + t);
                    
                }; break;
                case ')':{
                    
                };break;
                case '+':
                case '-':
                    lastop = ch;
                    break;
                default:
                    // numbers
                    int num = 0;
                    while ((i) < len && s[i] <= '9' && s[i] >= '0') {
                        num = num * 10 + ch - '0';
                        i++;
                    }
                    i--;
                    val = lastop == '-' ? (val - num) : (val + num);
            }
        }
        
        return val;
    }
};

 好了,来个简洁的,因为只涉及到加减法,其实我们可以把括号全部化简掉,在这个过程中应用负负得正的这些规律,正确得到多层括号内数值最终的符号:

class Solution {
public:
    int calculate(string s) {
        vector<int> sign;
        sign.push_back(1);
        
        char last_op = '+';
        int len = s.size();
        
        long val = 0;
        
        for (int i=0; i<len; i++) {
            char ch = s[i];
            switch(ch) {
                case ' ':
                    break;
                case '+':
                case '-':
                    last_op = ch;
                    break;
                case '(':
                    // enter a new sign context
                    sign.push_back(sign.back() * (last_op == '-' ? -1 : 1));
                    last_op = '+';
                    break;
                case ')':
                    // exit a sign context
                    sign.pop_back();
                    break;
                default:
                    // numbers;
                    int num = 0;
                    while (i < len && s[i] >= '0' && s[i] <= '9') {
                        num = num * 10 + s[i] - '0';
                        i++;
                    }
                    i--;
                    val += (last_op == '-'?-1:1) * sign.back() * num;
            }
        }
        return val;
    }
};
原文地址:https://www.cnblogs.com/lailailai/p/4565007.html