Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, +
, -
, *
, /
operators and empty spaces. The integer division should truncate toward zero.
You may assume that the given expression is always valid.
Some examples:
"3+2*2" = 7 " 3/2 " = 1 " 3+5 / 2 " = 5
class Solution {
public:
/*algorithm:RPN solution
1)conver it to RPN expression
2)compute the RPN
space O(n)
we can optimize this to O(1)
*/
bool isOperator(string c){return c=="+" ||c=="-" || c=="*" ||c=="/";}
bool isOperator(char c){return c=='+' ||c=='-' || c=='*' ||c=='/';}
int eval(string op,int x,int y){
if(op == "+")return x+y;
else if(op == "-")return x- y;
else if(op == "*")return x*y;
else return x/y;
}
int evalRPN(vector<string>&exp){
stack<int>stk;
for(int i = 0;i < exp.size();i++){
if(isOperator(exp[i])){
int r = stk.top();stk.pop();
int l = stk.top();stk.pop();
stk.push(eval(exp[i],l,r));
}else{
stk.push(atoi(exp[i].c_str()));
}
}
return stk.top();
}
//"3+2*2 + 3*4==>3 2 2 * + 3 4 * +
void converRPN(string s,vector<string>&expr)
{
unordered_map<string,int>pTable={
{"+",1},{"-",1},{"*",2},{"/",2},
{"#",0}
};
stack<string>inStk;
inStk.push("#");
int next;
for(int i = 0;i < s.size();){
char c = s[i];
next = i + 1;
if(isdigit(c)){
int start = i;
while(i < s.size() && isdigit(s[i]))++i;
expr.push_back(s.substr(start,i-start));
next = i;
}else if(isOperator(c)){
string op;
op.append(1,c);
if(pTable[op] > pTable[inStk.top()]){
inStk.push(op);
}else{
while(pTable[inStk.top()] >= pTable[op]){
expr.push_back(inStk.top());
inStk.pop();
}
inStk.push(op);
}
}else if(c == '#'){
while(inStk.top() != "#"){
expr.push_back(inStk.top());
inStk.pop();
}
}
i = next;
}
}
int calculate(string s) {
vector<string>expr;
converRPN(s+"#",expr);
return evalRPN(expr);
}
};