题目:224. 基本计算器
难度: 困难
题目:
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
示例1
输入:s = "1 + 1"
输出:2
示例2
输入:s = " 2-1 + 2 "
输出:3
示例3
输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23
提示
- 1 <= s.length <= 3 * 105
- s 由数字、’+’、’-’、’(’、’)’、和 ’ ’ 组成
- s 表示一个有效的表达式
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/basic-calculator/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
根据题意,需要我们在一堆字符串中将数字相加减得出最后结果。由提示可知,s是有效的表达式,不需要考虑各类格式输入错误。
该题的麻烦之处在于括号,遇到括号时就不能直接相加减了。根据数学知识,计算带括号的一种方法也就是去括号法,比较适合编程实现。也就是说,每遇到一个’(‘都直接去掉它然后进行加减计算,从左往右计算,遇到’)‘则恢复之前’(‘的计算。
因此可以利用符号函数,’+‘符号不变,’-‘符号取反。因为遇到’(’、时用去括号法可能会修改符号,而遇到’)‘又需要恢复到原来的情况,所以使用栈,遇到’(‘时将当前符号压栈,遇到’)'时出栈,保存了现场。
在下面的代码里,sign用于符号计算,每次加减时乘上sign,而stk栈则用于遇到括号时在当前栈顶修改,弹出栈时不改变之前的符号。
解题代码
class Solution {
public:
int calculate(string s) {
stack<int> stk;//遇到(时将当前符号值压栈,遇到)则出栈
stk.push(1);//默认为1
int sign = 1;//1为+,-1为-
int sum = 0;
int len = s.size();
int i = 0;
while (i < len)
{
if (s[i] == ' ')
{
i++;
}
else if (s[i] == '+')
{
sign = stk.top();//‘+’则不需要修改符号
i++;
}
else if (s[i] == '-')
{
sign = -stk.top();//'-'需要将当前符号取反
i++;
}
else if (s[i] == '(')
{
stk.push(sign);//根据去符号法,将当前符号压栈,遇到‘)’出栈
i++;
}
else if (s[i] == ')')
{
stk.pop();//一对括号外的元素符号不变
i++;
}
else
{
long num = 0;
while (i < len && s[i] >= '0'&& s[i] <= '9')//因为数字可能是一串,如123
{
num = num * 10 + s[i] - '0';
i++;
}
sum += sign * num;
}
}
return sum;
}
};
解题感悟
困难题,一开始没做出来,看了题解才恍然大悟。。。虽然感觉要使用栈,但是用了多个栈保存什么括号符号搞得特别复杂。
其实不必这么复杂,去括号法+栈轻松解决问题,做了个寂寞。。