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.
这道题是实现一个包含加减和括号的简易计算器,题目难度为Medium。
由于存在括号来改变运算优先级,而且括号可能层层嵌套,所以很自然会想到这里需要用到栈。运算符只有加和减,这样我们可以根据括号之前的运算符来去掉括号,括号之前如果是加号,直接去掉这对括号,如果是减号去掉括号的同时括号之内的运算符要取反(加变减,减变加),这样就可以递归地去掉所有括号。
在实现时不必采用递归,也不用真去掉括号,只需要知道每个运算符在去掉所有括号之后变成何种运算符就可以了。这里可能存在层层嵌套的括号,因而括号之前的符号在转换之后需要进栈,这样可以方便知道本括号内的运算符如何转换。具体地,在遍历到数字时,将数字按十进制移位累加得到当前的数字。在遍历到‘+’或‘-’时,表明前面已经出现一个数,我们根据记录的上一步运算,将这个数累加或累减到最终结果上,同时将记录的数字清零,这里上一步运算符是经转换之后的运算符。然后根据栈顶的符号来对遍历到的运算符进行转换,如果栈顶是1,表明左括号之前是‘+’,这样运算符不变;如果栈顶是-1,表明左括号之前是‘-’,运算符需要取反。遍历到‘(’时,将上一个运算符进栈,以便对括号之内的运算符进行转换。遍历到‘)’时,说明这对括号已经结束,此时需要出栈,将这对括号之前的符号退出。最后加上末尾的数字计算就完成了。具体代码:
class Solution {
public:
int calculate(string s) {
stack<int> sign;
int rst = 0, num = 0;
int lastSign = 1;
sign.push(1);
for(auto ch:s) {
if(ch >= '0' && ch <= '9') {
num = num*10+ch-'0';
}
else if(ch == '(') {
sign.push(lastSign);
}
else if(ch == '+' || ch == '-') {
rst += lastSign*num;
num = 0;
lastSign = ((ch == '+') ? 1 : -1) * sign.top();
}
else if(ch == ')') {
sign.pop();
}
}
rst += lastSign*num;
return rst;
}
};