问题描述
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; } }