给你一个字符串表达式 s
,请你实现一个基本计算器来计算并返回它的值。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()
。
示例 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
表示一个有效的表达式- '+' 不能用作一元运算(例如, "+1" 和
"+(2 + 3)"
无效) - '-' 可以用作一元运算(即 "-1" 和
"-(2 + 3)"
是有效的) - 输入中不存在两个连续的操作符
- 每个数字和运行的计算将适合于一个有符号的 32位 整数
class Solution {
public:
// 计算给定字符串表达式的值
int calculate(string s) {
// 使用栈来保存符号,初始化为 1
stack<int> ops;
ops.push(1);
// 符号,初始化为 1,表示正数
int sigh = 1;
// 结果,初始化为 0
int ret = 0;
// 字符串 s 的长度
int n = s.size();
// 字符串 s 的索引
int i = 0;
// 遍历字符串 s
while (i < n) {
// 跳过空格
if (s[i] == ' ')
i++;
// 遇到 '+' 号,更新符号为栈顶的符号
else if (s[i] == '+') {
sigh = ops.top();
i++;
}
// 遇到 '-' 号,更新符号为栈顶符号的相反数
else if(s[i]=='-'){
sigh=-ops.top();
i++;
}
// 遇到 '(' 号,将当前符号压入栈中
else if(s[i]=='('){
ops.push(sigh);
i++;
}
// 遇到 ')' 号,弹出栈顶的符号
else if(s[i]==')'){
ops.pop();
i++;
}
// 遇到数字
else{
// 使用 long 类型来避免在 32 位整数范围内的溢出
long num = 0;
// 循环累加数字
while(i < n && s[i] >= '0' && s[i] <= '9'){
num = num * 10 + s[i] - '0';
i++;
}
// 更新结果
ret += sigh * num;
}
}
// 返回最终的计算结果
return ret;
}
};
代码采用了栈来保存符号,并使用符号来控制数字的正负。具体的思路如下:
- 初始化一个栈
ops
,将1入栈,表示初始符号为正数。 - 初始化一个变量
sigh
,表示当前符号,默认为1(表示正数)。 - 初始化一个变量
ret
,表示最终结果,默认为0。 - 遍历输入字符串
s
,将索引初始化为0。 - 在循环中处理每个字符:
- 如果是空格,则跳过,继续处理下一个字符。
- 如果是
+
号,则更新符号为栈顶符号,将索引向后移动一位。 - 如果是
-
号,则更新符号为栈顶符号的相反数,将索引向后移动一位。 - 如果是
(
号,则将当前符号压入栈中,将索引向后移动一位。 - 如果是
)
号,则弹出栈顶的符号,将索引向后移动一位。 - 如果是数字,则将数字累加到结果上,根据当前符号的正负进行累加,并将索引向后移动到数字的结束位置。
- 循环结束后,返回最终的计算结果。
这样就可以按照给定字符串表达式的规则计算出最终的值了。