题解 | #表达式求值#
表达式求值
http://www.nowcoder.com/practice/9566499a2e1546c0a257e885dfdbf30d
啃了一下午A了,不容易啊,记录下思路:
1、preExecute() 预处理函数,先将字符串处理成List集合,主要为了转换多位整数
2、buildTree() 递归建树,将表达式转换为表达式树,其中易错点在处理负数的地方
3、print() 将表达式树后序遍历,将遍历结果存放在List中
4、calculate() 计算后序遍历List,从左到右遍历若元素是运算符,则将栈顶部前两个数字出栈并计算,否则,将该元素入栈,遍历完毕取栈顶元素返回。
5、打印结果
public class ExpressionTree { private static int maxn = 1000; private static int lch[] = new int[maxn], rch[] = new int[maxn]; private static String op[] = new String[maxn]; private static int nc = 0; private static List<String> postStr = new ArrayList<>(); private static Set<String> set = new HashSet<>(); static { set.addAll(Arrays.asList("+", "-", "*", "/")); lch[0] = rch[0] = 100000; } private static int buildTree(List<String> expression, int x, int y) { int i, c1 = -1, c2 = -1, p = 0; int u; if (y - x == 1) {//only rest one char,set num of calculated. u = ++nc; lch[u] = 100000; rch[u] = 100000; op[u] = expression.get(x); return u; } else if (y - x == 0) {//可能出现负数的情况,如:-1*(-1-1),此时c1在第一个'-'号的位置,而起点x与之相同 u = ++nc; lch[u] = 100000; rch[u] = 100000; op[u] = "0"; return u; } for (i = x; i < y; i++) { switch (expression.get(i)) { case "(": p++; break; case ")": p--; break; case "-": case "+": if (p == 0) c1 = i; break; case "*": case "/": if (p == 0) c2 = i; break; } } if (c1 < 0) c1 = c2; if (c1 < 0) return buildTree(expression, x + 1, y - 1); u = ++nc; lch[u] = buildTree(expression, x, c1); rch[u] = buildTree(expression, c1 + 1, y); op[u] = expression.get(c1);//set sign of calculated; return u; } //(a+b)*c private static void print(int root) { if (root == 100000) return; print(lch[root]); print(rch[root]); if(op[root]!=null)postStr.add(op[root]); // System.out.println(op[root]); } /** * 后缀表达式计算结果,a b + c * d e / + * 从左到右开始计算, * 遇到数字进栈,遇到运算符时将栈顶前2个元素出栈计算再将结果入栈。 * * @param postStr * @return */ private static int calculate(List<String> postStr) { Stack<String> stack = new Stack<>(); for (String item : postStr) { if (set.contains(item)) { int operNum2 = Integer.valueOf(stack.pop()); int operNum1 = Integer.valueOf(stack.pop()); int result = 0; switch (item) { case "+": result = operNum1 + operNum2; break; case "-": result = operNum1 - operNum2; break; case "*": result = operNum1 * operNum2; break; case "/": result = operNum1 / operNum2; break; } stack.push(String.valueOf(result)); } else { stack.push(item); } } return Integer.valueOf(stack.pop()); } //-1*(-1-1) private static List<String> preExecute(String e) { List<String> result = new ArrayList<>(); int index = 0; int i; for (i = 0; i < e.length(); i++) { if (!Character.isDigit(e.charAt(i))) { if (index < i) result.add(e.substring(index, i)); result.add(String.valueOf(e.charAt(i))); index = i + 1; } } if (index < i) result.add(e.substring(index, i)); return result; } public static void main(String[] args) { Scanner sa = new Scanner(System.in); while (sa.hasNext()) { String expression = sa.next(); List<String> list = preExecute(expression); int root = buildTree(list, 0, list.size()); print(root); int result = calculate(postStr); System.out.println(result); } } }