基本计算器 II
难度:
标签:
题目描述
给你一个字符串表达式 s
,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1]
的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()
。
示例 1:
输入:s = "3+2*2" 输出:7
示例 2:
输入:s = " 3/2 " 输出:1
示例 3:
输入:s = " 3+5 / 2 " 输出:5
提示:
1 <= s.length <= 3 * 105
s
由整数和算符('+', '-', '*', '/')
组成,中间由一些空格隔开s
表示一个 有效表达式- 表达式中的所有整数都是非负整数,且在范围
[0, 231 - 1]
内 - 题目数据保证答案是一个 32-bit 整数
代码结果
运行时间: 68 ms, 内存: 0.0 MB
/*
* 题目思路:
* 1. 使用一个栈来存储每个操作数,根据当前的运算符来决定如何处理栈顶元素。
* 2. 使用Java Stream进行最终的栈元素求和。
*/
import java.util.Stack;
public class BasicCalculator {
public int calculate(String s) {
Stack<Integer> stack = new Stack<>();
int num = 0;
char sign = '+';
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
num = num * 10 + (c - '0');
}
if (!Character.isDigit(c) && c != ' ' || i == s.length() - 1) {
if (sign == '+') {
stack.push(num);
} else if (sign == '-') {
stack.push(-num);
} else if (sign == '*') {
stack.push(stack.pop() * num);
} else if (sign == '/') {
stack.push(stack.pop() / num);
}
sign = c;
num = 0;
}
}
return stack.stream().mapToInt(Integer::intValue).sum();
}
}
解释
方法:
这个题解使用了一个栈来模拟计算过程。遍历字符串 s 中的每个字符,如果当前字符是数字,则更新当前数 cur;如果当前字符是运算符,则根据上一个运算符 op 来决定如何处理当前数,并更新上一个运算符为当前运算符。具体来说:
1. 如果上一个运算符是加号,则将当前数压入栈;
2. 如果上一个运算符是减号,则将当前数的相反数压入栈;
3. 如果上一个运算符是乘号,则将栈顶元素弹出,与当前数相乘后压入栈;
4. 如果上一个运算符是除号,则将栈顶元素弹出,与当前数相除后压入栈,注意处理除数为负数的情况。
最后将栈中所有元素求和即为最终结果。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在处理每个数字后,需要加一个额外的'+'到字符串末尾来确保最后一个数字被正确处理?
▷🦆
在处理除法时,为什么选择用0减去正数除法的结果来处理负数情况,这种做法是否有可能导致结果错误?
▷🦆
在遇到乘号或除号时直接修改栈顶元素而不是先出栈再压入的做法,这种处理有什么优点或潜在的风险?
▷🦆
在这种解法中,如果输入字符串包含错误或非法字符(如字母或特殊字符),算法将如何响应?
▷相关问题
基本计算器
给你一个字符串表达式 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位 整数
给表达式添加运算符
给定一个仅包含数字 0-9
的字符串 num
和一个目标值整数 target
,在 num
的数字之间添加 二元 运算符(不是一元)+
、-
或 *
,返回 所有 能够得到 target
的表达式。
注意,返回表达式中的操作数 不应该 包含前导零。
示例 1:
输入: num =
"123", target = 6
输出: ["1+2+3", "1*2*3"]
解释: “1*2*3” 和 “1+2+3” 的值都是6。
示例 2:
输入: num =
"232", target = 8
输出: ["2*3+2", "2+3*2"]
解释: “2*3+2” 和 “2+3*2” 的值都是8。
示例 3:
输入: num =
"3456237490", target = 9191
输出: []
解释: 表达式 “3456237490” 无法得到 9191 。
提示:
1 <= num.length <= 10
num
仅含数字-231 <= target <= 231 - 1