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; } };