227. 基本计算器 II
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。
示例 1:
输入: “3+2*2”
输出: 7
示例 2:
输入: " 3/2 "
输出: 1
示例 3:
输入: " 3+5 / 2 "
输出: 5
方法1
-
总思路:全部转换为+号,把 *, / , - 都先计算出来,放到stack里,最后把stack里的数全部相加就是结果。
// 遍历s的每个字符,如果是数字,和后面继续组成数字tempNum, // 并且根据前面的符号和数据,计算出结果放到stack中 // 如果是'', 继续遍历 // 如果是运算符号,更新lastOp
class Solution {
public int calculate(String s) {
Stack<Integer> numStack = new Stack<>();
char[] arr = s.toCharArray();
char lastOp = '+';
for(int i = 0; i < arr.length; i++) {
if(arr[i] == ' ') continue;
if(Character.isDigit(arr[i])) {
int tempNum = arr[i] - '0';
while(++i < arr.length && Character.isDigit(arr[i])) {
tempNum = tempNum * 10 + (arr[i] - '0');
}
i--;
if(lastOp == '+') numStack.push(tempNum);
else if(lastOp == '-') numStack.push(-tempNum);
else {
numStack.push(res(lastOp, numStack.pop(), tempNum));
}
}else {
lastOp = arr[i];
}
}
int ans = 0;
for(int num : numStack) {
ans += num;
}
return ans;
}
private int res(char lastOp, int num1, int num2) {
int ans = 0;
if(lastOp == '+') { // '+' '-' 两种情况可以不写
ans = num1 + num2;
}else if(lastOp == '-') {
ans = num1 - num2;
}else if(lastOp == '*') {
ans = num1 * num2;
}else if(lastOp == '/') {
ans = num1 / num2;
}
return ans;
}
}
方法2
转换为后缀表达式
后缀表达式转换为
224. 基本计算器
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。
示例 1:
输入: “1 + 1”
输出: 2
示例 2:
输入: " 2-1 + 2 "
输出: 3
示例 3:
输入: “(1+(4+5+2)-3)+(6+8)”
输出: 23
-
增加了括号,括号可以递归计算
-
再普通一点,加上乘法和除法
-
和上一题思想类似,
-
遍历字符串
-
如果是数字,和后面的字符组成数字,再根据前面的符号计算结果,添加到栈中 ,即转换为加号
-
如果字符是运算符,则
-
问题来了,由于这题多了括号,而且添加了递归操作,就变得复杂起来。
-
三个重点理解
- 1.原来是数字,再根据前面的符号相加,添加到栈中,引到这里会出现问题:(1 + (4 + 5))中的(4 + 5)stack1递归回来后,num = 9, 要添加到(1)这层括号的stack0里,而此时递归回来后,ch = ‘(’, 如果按照上面的逻辑,这里不是数字,num=4+5就无法添加到stack0中;
- 所以当ch为数字时,更新num;
- 2.当ch不为数字时,操作num和op, 重点重中之重:eg:(1 * 1 + 1 ), 当遍历到 * 时,此时num = 1, op = + , ch = *, 搞清楚这三个变量之间的关系,执行:case ‘+’ : stack.push(num=1), num = 0; op = ch;
- case ‘+’: 执行ch = ‘*’ 前面的数字操作,1 + ;添加到stack里
- num = 0; 因为ch = ‘*’ , num要更新为0,具体数字取决于下一个ch
- op = ch; 更新操作符,方便下一次遇到非数字+时,执行 + 前面的操作,执行 case ‘*’ : stack.push(stack.pop() * num);
- eg: (1 + (4 - 5))
- 3 递归:if(ch == ‘(’) {++i[0]; num = dfs(s, i);}
- 执行完(4-5)后,回来时,ch = ‘(’, op = ‘+’; num = 4 - 5 = -1 ; 添加到stack0中;
- 遇到‘)’ ,跳出循环,计算完(4-5)stack1中的数字,返回num = -1 给在stack0中的();
- 4 为了一直遍历s, 不被递归的局部i打乱,这里i不止int型变量,而是int[] i = new int[1], 中的i[0], 即是对象,dfs(s, i) 是浅拷贝i, 即栈中的参数全部指向堆中的对象。
方法一:遍历字符,操作符转为加号,递归计算括号
class Solution {
public int calculate(String s) {
int[] i = new int[1];
return dfs(s, i);
}
private int dfs(String s, int[] i) {
Deque<Integer> stack = new LinkedList<>();
int num = 0;
char op = '+';
for(; i[0] < s.length(); i[0]++) {
char ch = s.charAt(i[0]);
if(ch == '(') {
++i[0];
num = dfs(s, i);
}
if(Character.isDigit(ch)) {
num = num * 10 + (ch - '0');
}
if(!Character.isDigit(ch) && (ch != ' ') || i[0] == s.length() - 1) {
switch(op) {
case '+':
stack.push(num); break;
case '-':
stack.push(-num); break;
case '*':
stack.push(stack.pop() * num);break;
case '/':
stack.push(stack.pop() / num);break;
}
op = ch;
num = 0;
}
if(ch == ')') {
break;
}
}
int res = 0;
while(!stack.isEmpty()) {
res += stack.pop();
}
return res;
}
}