给你一个字符串表达式 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 * 105
s
由数字、'+'
、'-'
、'('
、')'
、和' '
组成s
表示一个有效的表达式- '+' 不能用作一元运算(例如, "+1" 和
"+(2 + 3)"
无效) - '-' 可以用作一元运算(即 "-1" 和
"-(2 + 3)"
是有效的) - 输入中不存在两个连续的操作符
- 每个数字和运行的计算将适合于一个有符号的 32位 整数
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/basic-calculator/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
- 定义
Deque<Integer>
来作为栈,存储中间结果。定义num
用于记录当前解析的数字,sign
记录前一个运算符的类型。for
循环遍历字符串中的每个字符。如果是数字,就计算num
;如果是左括号(
,则递归计算括号内的表达式,并将结果赋给num
。- 遇到运算符或字符串末尾时,根据
sign作为
不同的运算符将num
或其操作后的结果压入栈。- 如果遇到右括号
)
,则结束递归调用。- 最后,将栈内所有数字相加,得到最终结果。
class Solution {
public int calculate(String s) {
return calculateI(s);
}
//方法一:栈
//遇到括号时,无论多少层括号嵌套,通过calcu函数递归调用自己,都可以将括号中的算式化简成一个数字。
//换句话说,括号包含的算式,我们直接视为一个数字就行了。
//时间复杂度O(n),空间复杂度O(n)
private int calculateI(String s) {
if (s == null || s.length() == 0) {
throw new IllegalArgumentException("Input string is null or is empty.");
}
return calcu(s);
}
private int index = 0;
private int calcu(String s) {
Deque<Integer> stack = new ArrayDeque<>();
int num = 0;
char sign = '+';
for (; index < s.length(); index++) {
//移动到下一个字符
char c = s.charAt(index);
if (Character.isDigit(c)) {
num = num * 10 + (c - '0');
}
if (c == '(') {
//跳过左括号开始递归
index++;
num = calcu(s);
}
//如果遇到运算符、空格或者到达字符串末尾,根据上一个符号处理数字
if (!Character.isDigit(c) && c != ' ' || index == s.length() - 1) {
switch (sign) {
case '+':
stack.push(num);
break;
case '-':
stack.push(-num);
break;
case '*':
stack.push(stack.pop() * num);
break;
case '/':
stack.push(stack.pop() / num);
break;
}
sign = c;
num = 0;
}
if (c == ')') {
//如果为右括号,结束递归(返回后,i指向新生成的数字)
break;
}
}
int ans = 0;
while (!stack.isEmpty()) {
ans += stack.pop();
}
return ans;
}
}