欢迎访问LeetCode题解合集
题目描述
给你一个字符串表达式 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 * 10^5
s
由数字、'+'
、'-'
、'('
、')'
、和' '
组成s
表示一个有效的表达式
题解:
法一:
双栈模拟。
一个数字栈,一个符号栈。
先把 s
中的空格去掉。。。
从左往右遍历 s
:
- 若
s[i]
为(
,压入符号栈 - 若
s[i]
为+/-
,在把运算符压入栈前,需要先把栈中能计算的都算出来。然后判断-x
或者(-x
或者-(...)
情况,向数字栈中压入一个0
,表示0 +/- ...
- 若
s[i]
为)
,在符号栈中未遇到(
时,不停的计算,并把(
出栈
最后,符号栈不为空继续计算。
时间复杂度:$O(n)$
额外空间复杂度:$O(n)$
class Solution {
private:
vector<char> ops;
vector<int> nums;
public:
void calc() {
int a = nums.back(); nums.pop_back();
int b = nums.back(); nums.pop_back();
if ( ops.back() == '+' ) b += a;
else b -= a;
nums.emplace_back( b );
ops.pop_back();
}
int calculate(string s) {
string t = "";
for ( char ch : s ) {
if ( ch == ' ' ) continue;
t += ch;
}
int ans;
for ( int i = 0, j; i < t.size(); ++i ) {
if ( t[i] == '(' ) ops.emplace_back( t[i] );
else if ( t[i] == '+' || t[i] == '-' ) {
if ( !i || t[i - 1] == '(' )
nums.emplace_back( 0 );
if ( i && !isdigit(t[i - 1]) && t[i + 1] == ')' )
nums.emplace_back( 0 );
while ( ops.size() && ops.back() != '(' ) calc();
ops.emplace_back( t[i] );
} else if ( isdigit(t[i]) ) {
j = i, ans = 0;
while ( j < t.size() && isdigit(t[j]) )
ans = ans * 10 + (t[j++] & 15);
i = j - 1;
nums.emplace_back( ans );
} else {
while( ops.back() != '(' ) calc();
ops.pop_back();
}
}
while ( ops.size() ) calc();
return nums.back();
}
};
/*
时间:12ms,击败:57.74%
内存:8.5MB,击败:30.48%
*/
法二:
考虑把所有的括号去掉,比如 1 - ( 2 + 3 )
,去掉括号后为 1 - 2 - 3
考虑使用 1
和 -1
分别代表正负号,括号内的正负号与括号外的正负号有关,所以我们需要使用一个符号栈,具体见代码:
class Solution {
private:
public:
int calculate(string s) {
vector<int> ops;
ops.emplace_back( 1 );
int sign = 1;
int ret = 0, ans;
for ( int i = 0, j; i < s.size(); ++i ) {
if ( s[i] == ' ' ) continue;
if ( s[i] == '+' ) sign = ops.back();
else if ( s[i] == '-' ) sign = -ops.back();
else if ( s[i] == '(' ) ops.emplace_back( sign );
else if ( s[i] == ')' ) ops.pop_back();
else {
ans = 0, j = i;
while ( j < s.size() && isdigit(s[j]) )
ans = ans * 10 + (s[j++] & 15);
ret += sign * ans;
i = j - 1;
}
}
return ret;
}
};
/*
时间:8ms,击败:92.43%
内存:7.8MB,击败:93.16%
*/