问题描述
Implement a basic calculator to evaluate a simple expression string.
The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .
You may assume that the given expression is always valid.
Some examples:
"1 + 1" = 2 " 2-1 + 2 " = 3 "(1+(4+5+2)-3)+(6+8)" = 23
Note: Do not use the eval built-in library function.
程序
第一种是普通的方法:先将表达式转成后缀表达式,然后再计算。(TLE)
将中缀表达式转为后缀表达式
中缀表达式转为后缀表达式的要点:
开始扫描;
数字时,加入后缀表达式;
运算符:
a. 若为 '(',入栈;
b. 若为 ')',则依次把栈中的的运算符加入后缀表达式中,直到出现'(',从栈中删除'(' ;
c. 若为 除括号外的其他运算符, 当其优先级高于除'('以外的栈顶运算符时,直接入栈。否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低 的或者遇到了一个左括号为止。·当扫描的中缀表达式结束时,栈中的的所有运算符出栈;
public List<String> getPostfixExpressionList(String s) {
List<String> list = new ArrayList<String>();
// preprocess
s = s.trim();
char[] cc = s.toCharArray();
String pro_s = "";
Stack<String> st = new Stack<String>();
for (int i = 0; i < cc.length; i++) {
char c = cc[i];
if (!Character.isDigit(c)) {
pro_s += " " + c + " ";
} else {
pro_s += c;
}
}
// operators priority
HashMap<String, Integer> opMap = new HashMap<String, Integer>();
opMap.put("+", 0);
opMap.put("-", 0);
opMap.put("*", 1);
opMap.put("/", 1);
String[] items = pro_s.split(" ");
for (int i = 0; i < items.length; i++) {
String item = items[i].trim();
if (item.length() == 0) {
continue;
}
if (item.equals("(")) {
st.push(item);
} else if (item.equals(")")) {
while (!st.peek().equals("(")) {
list.add(st.pop());
}
st.pop();
} else if (opMap.containsKey(item)) {
if (st.isEmpty() || st.peek().equals("(")
|| opMap.get(st.peek()) < opMap.get(item)) {
st.push(item);
} else {
while (!st.isEmpty() && !st.peek().equals("(")
&& opMap.get(st.peek()) >= opMap.get(item)) {
list.add(st.pop());
}
st.push(item);
}
} else {
list.add(item);
}
}
while (!st.isEmpty()) {
list.add(st.pop());
}
return list;
}
第二种是简化的方法,比较巧妙。
public class BasicCalculator {
public int calculate(String s) {
if (s == null || s.length() == 0) {
return 0;
}
// transform to postfix expression
BasicCalculatorII bs2 = new BasicCalculatorII();
List<String> postExpressionList = bs2.getPostfixExpressionList(s);
// calculate
Stack<Integer> calStack = new Stack<Integer>();
for (String ex : postExpressionList) {
if (ex.equals("+")) {
int n1 = calStack.pop();
int n2 = calStack.pop();
calStack.push(n1 + n2);
} else if (ex.equals("-")) {
int n1 = calStack.pop();
int n2 = calStack.pop();
calStack.push(n2 - n1);
} else if (ex.equals("*")) {
int n1 = calStack.pop();
int n2 = calStack.pop();
calStack.push(n2 * n1);
} else if (ex.equals("/")) {
int n1 = calStack.pop();
int n2 = calStack.pop();
calStack.push(n2 / n1);
} else {
calStack.push(Integer.valueOf(ex));
}
}
return calStack.peek();
}
// only have +, - operators
public int calculate2(String s) {
if (s == null || s.length() == 0) {
return 0;
}
s = s.trim();
int res = 0, sign = 1;
Stack<Integer> st = new Stack<Integer>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
int cur = c - '0';
while (i + 1 < s.length() && Character.isDigit(s.charAt(i + 1))) {
cur = cur * 10 + (s.charAt(i + 1) - '0');
++i;
}
res += sign * cur;
} else if (c == '+') {
sign = 1;
} else if (c == '-') {
sign = -1;
} else if (c == '(') {
st.push(res);
res = 0;
st.push(sign);
sign = 1;
} else if (c == ')') {
res = st.pop() * res + st.pop();
sign = 1;
}
}
return res;
}
}