Problem Description:
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.
Analysis:
The given expression only contains ‘+’, ‘-‘, and ‘(‘, ‘)’ and non-negative integer.
We could store the sign before ‘(’ into stack, then check and flip the coming signs and pop out the top sign when met ‘)’;
Code :
Easy Neat two stack version
sum the num with previous sign, when met the ‘(’ , push the late sum and sign before ‘(’ into two stack respectively.
when met ‘)’ , pop out the sign and previous sum in the two stack and computer the current sum.
int calculate(string s) {
stack<int> nums, ops;//two stack for operand and operators
int op = 0;
int sign = 1;
int sum = 0;
for (char c : s)
{
if (isdigit(c))
{
op = op * 10 + (c - '0');
}
else{
sum += sign * op;
op = 0;
if (c == '+') sign = 1;// current(right side) sign
if (c == '-') sign = -1;
if (c == '(') {//store the last total
nums.push(sum);
ops.push(sign);
sum = 0;
sign = 1;
}
if (c == ')' && ops.size()){
sum = ops.top() * sum + nums.top();
ops.pop();
nums.pop();
}
}
}
sum += sign * op;//-(2-3)
return sum;
}
One stack, flipping the sign depends on the top of sign stack.
int calculate(string s) {
stack<int> signs;
int sign = 1;
int sum = 0;
int op = 0;
signs.push(1);
for (char c : s)
{
if (isdigit(c))
{
op = op * 10 + c - '0';
}
else {
if (c == '+' || c == '-')
{
sum = sum + signs.top() * sign * op;//check and flip the sign
op = 0;
sign = (c == '+'? 1 : -1);
}
if (c == '(')
{
signs.push(sign * signs.top()); //push the sign
sign = 1;
}
else if (c == ')')
{
sum = sum + signs.top() * sign * op; //current char is ')', we need calculate the sum before ')', then pop out the sign
num = 0;
signs.pop();
sign = 1;
}
}
}
if (op)
sum = sum + signs.top() * sign * op;
return sum;
}
Another one stack solution:
int calculate(string s) {
int n = s.size();
stack<int> stk; //store the previous sum and sign
int sign = 1;
int num = 0;
int sum = 0;
for (int i = 0; i < n; ++i)
{
if (isdigit(s[i]))
{
num = num * 10 + (s[i] - '0');
}
else{
if (s[i] == '-' || s[i] == '+')
{
sum += sign * num;
sign = s[i] == '-' ? -1 : 1;
num = 0;
}
else if (s[i] == '(')
{
stk.push(sum);
stk.push(sign);
sum = 0;
sign = 1;
}
else if (s[i] == ')')
{
sum += sign * num;
sign = stk.top();
stk.pop();
sum = stk.top() + sign * sum;
stk.pop();
sign = 1;
num = 0;
}
}
}
sum += sign * num;//don't forget this sum at last for axample: 2 - 1
return sum;
}
};