今日每日一题是Leetcode224. 基本计算器,题意如下:
实现一个基本的计算器来计算一个简单的字符串表达式 s 的值。
1 <= s.length <= 3 * 105
s 由数字、’+’、’-’、’(’、’)’、和 ’ ’ 组成
s 表示一个有效的表达式
例:输入:s = “(1+(4+5+2)-3)+(6+8)”
输出:23
这道题虽然是个困难难度的题,但是思路却非常简单。基本上都能想到用一个栈来存表达式。因为这道题只有加减运算,只有括号是最先优先级。所以我们将表达式入栈当遇到右括号的时候出栈,计算到左括号为止,再把这个值入栈。这样就完成了先算括号中的数。只是这个题需要注意的细节有很多,比如括号前面的正负号等等。但是这样写起来较为麻烦,需要字符串和数字来回转换,细节太多。
嫌麻烦我们就考虑别的方法,在加减运算中,括号前如果是正号那么我们可以当这个括号不存在,括号前如果是负号我们想把括号去掉,相当于把括号中的每一个符号由正变负,由负变正。 所以我们在把所有括号去掉后,每个数的正负只取决于它前面负号的个数。 我们用一个栈来存每个数的正负情况。每次遇到一个正号,后面数的正负和栈顶符号相同。每次遇到一个负号,后面数的正负和栈顶符号相反。如果遇到左括号将括号前的符号入栈,如果遇到右括号就将栈顶弹出。这样就记录了每个数的正负翻转情况,相当于把所有的括号展开了,只需要按顺序运算即可。
c++参考代码:
class Solution {
public:
int calculate(string s) {
int n=s.size();
int ans=0;
stack<int> sign;
int now=1;
sign.push(now);
for(int i=0;i<n;i++)
{
if(s[i]==' ')
{continue;}
else if(s[i]=='+')
{now=sign.top();}
else if(s[i]=='-')
{now=-1*sign.top();}
else if(s[i]=='(')
{sign.push(now);}
else if(s[i]==')')
{sign.pop();}
else
{
int number = 0;
while (i < s.length() && s[i] >= '0' && s[i] <= '9')
{
number = number * 10 + (s[i] - '0');
i++;
}
i--;
ans+=now*number;
}
}
return ans;
}
};
时间复杂度:O(N)。
参考资料
·力扣官方题解