题目:
题解一:
难点:
- 括号优先计算
- 正负号和运算符加减号区分
- 运算符优先级
解决方案:
- 运算符栈存放运算符
- 数字栈存放数字
- 每次计算从数字栈弹出两个数字,运算符栈弹出一个运算符
- 数字前面的+,-为正负号,数字后面的+,-为运算符号,设置一个标记用以区分
- 遇到括号优先计算
public int expressCalculate(String s) {
if (s == null || s.length() == 0) {
return 0;
}
// 替换括号
s = s.replaceAll("\\[", "(");
s = s.replaceAll("\\{", "(");
s = s.replaceAll("\\]", ")");
s = s.replaceAll("\\}", ")");
// 加一个小括号在最外层
if (s.charAt(0) != '(') {
s = "(" + s + ")";
}
Stack<Character> operatorStack = new Stack<>();
Stack<Integer> numberStack = new Stack<>();
boolean flag = false;
for (int i = 0; i < s.toCharArray().length; i++) {
char c = s.charAt(i);
if (c == '(') {
operatorStack.push(c);
} else if (c == ')') {
// 遇到右括号就计算
while (operatorStack.peek() != '(') {
calculateAndPush(numberStack, operatorStack);
}
operatorStack.pop();
} else if (flag) {
// 运算符,如果栈顶的运算符优先级高就需要先计算
while (priority(operatorStack.peek(), c)) {
calculateAndPush(numberStack, operatorStack);
}
operatorStack.push(c);
// 运算符结束,后面的+,-就是正负号
flag = false;
} else {
// 数字
int j = i;
// 正负号
if (c == '-' || c == '+') {
i++;
}
while (Character.isDigit(s.charAt(i))) {
i++;
}
// 转换数字
int number = Integer.valueOf(s.substring(j, i));
numberStack.push(number);
// 数字结束,后面+,-就是运算符
flag = true;
// for 循环后面i++,所以这里需要先减一
i--;
}
}
return numberStack.pop();
}
private boolean priority(char stackOperator, char currentOperator) {
if (stackOperator == '(') {
return false;
}
if ((stackOperator == '+' || stackOperator == '-') && (currentOperator == '*' || currentOperator == '/')) {
return false;
}
return true;
}
private void calculateAndPush(Stack<Integer> numberStack, Stack<Character> operatorStack) {
// 注意:栈的顺序是反的,这里先出栈的是参数二
int value2 = numberStack.pop();
int value1 = numberStack.pop();
char operator = operatorStack.pop();
int result = 0;
switch (operator) {
case '+' : result = value1 + value2; break;
case '-' : result = value1 - value2; break;
case '*' : result = value1 * value2; break;
case '/' : result = value1 / value2; break;
}
numberStack.push(result);
}
时间复杂度:O(N)
题解二:脚本执行
把表达式作为脚本执行,使用JavaScript脚本直接计算结果。
public int expressCalculate(String s) throws Exception {
if (s == null || s.length() == 0) {
return 0;
}
// 替换括号
s = s.replaceAll("\\[", "(");
s = s.replaceAll("\\{", "(");
s = s.replaceAll("\\]", ")");
s = s.replaceAll("\\}", ")");
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("Nashorn");
return (int) scriptEngine.eval(s);
}