Poison

227. Basic Calculator II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class Solution {
private static final Map<Character, Integer> OPERATOR_TO_PRECEDENCE_MAP = new HashMap<>();

static {
OPERATOR_TO_PRECEDENCE_MAP.put('+', 0);
OPERATOR_TO_PRECEDENCE_MAP.put('-', 0);
OPERATOR_TO_PRECEDENCE_MAP.put('*', 1);
OPERATOR_TO_PRECEDENCE_MAP.put('/', 1);
}

public int calculate(String s) {
s = s.replaceAll(" ", "");

// 思路:将所有的操作符按照二元操作符处理
Stack<Character> operatorStack = new Stack<>();
Stack<Integer> numStack = new Stack<>();
numStack.push(0); // 放入 0 是为了处理纯负数的情况,如表达式 '-5', 此时等同于表达式 '0-5'

for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
// 将后续的数字收集并统一转换为整数
int num = 0;
while (i < s.length() && Character.isDigit(s.charAt(i))) {
num = num * 10 + (s.charAt(i) - '0');
i++;
}
// i == s.length() or s.charAt(i) is not digit
i--;
numStack.push(num);
} else {
// 注意此处是 while 而不是 if, 可以用 "1*2-3/4+5*6-7*8+9/10" 进行验证,即保证从左到右计算,若使用 if 会导致乘除法计算的结果全部位于栈中,最后 "2-0+30-56+0" 从右到左计算而得到错误结果。while 的另一层含义为使操作符栈中的操作符优先级递增,以保证最后 while 计算结果正确
while (!operatorStack.isEmpty() && OPERATOR_TO_PRECEDENCE_MAP.get(operatorStack.peek()) >= OPERATOR_TO_PRECEDENCE_MAP.get(c)) {
calc(operatorStack, numStack);
}
operatorStack.push(c); // 不要忘记将操作符入栈
}
}

// 注意此处是 while, 如表达式 '3+2*2', 最后操作符栈中有两个操作符,操作数栈中有三个操作数
while (!operatorStack.isEmpty()) {
calc(operatorStack, numStack);
}

return numStack.pop();
}

private void calc(Stack<Character> operatorStack, Stack<Integer> numStack) {
char operator = operatorStack.pop();
int b = numStack.pop(), a = numStack.pop();
switch (operator) {
case '+':
numStack.push(a + b);
break;
case '-':
numStack.push(a - b);
break;
case '*':
numStack.push(a * b);
break;
case '/':
numStack.push(a / b);
break;
default:
throw new IllegalArgumentException("Unsupported operator: " + operator);
}
}
}
Reference

227. Basic Calculator II
面试题 16.26. 计算器