标签:
给定一个正确的表达式(不用担心不规范的输入),比如2-1-1, 通过在不同位置添加左右括号,改变求值的优先级顺序,求出所有的这些值;
Example 1
Input: "2-1-1"
.
((2-1)-1) = 0 (2-(1-1)) = 2
Output: [0, 2]
Example 2
Input: "2*3-4*5"
(2*(3-(4*5))) = -34 ((2*3)-(4*5)) = -14 ((2*(3-4))*5) = -10 (2*((3-4)*5)) = -10 (((2*3)-4)*5) = 10
Output: [-34, -14, -10, -10, 10]
这个题目应该没有便捷的解法,只能全部的都尝试一遍;当然仅仅需要暴力的枚举一遍,也没有什么有趣的地方,我觉得有趣的地方体现在下面两点:
1. 这个题目可以用递归的方法求解,因为,假设遇到某个操作符,如果知道了左边的结果,再计算出右边的结果,那么只要把左右两边的结果合并起来,就可以了;
2. 当然如果直接按照递归去做,会出现一个问题,(大概会超时,我没有提交这样的代码);假设在得到了某个操作符两边的结果后,到了下一个操作符,递归计算的时候,任然会需要前面一个操作符(左边的)的结果,所以必须要把已经计算过的结果要cache起来;
最后的代码如下:
private final static long base = 100001; private Map<Long, List<Integer>> cache = new HashMap<>(); private List<Integer> diffWaysToCompute(char[] cs, int start, int end) { long key = base * start + end; if (cache.containsKey(key)) { return cache.get(key); } boolean isNumber = true; for (int i = start; i < end; i++) { if (isOperator(cs[i])) { isNumber = false; break; } } List<Integer> result = new ArrayList<>(); if (isNumber) { result.addAll(toNum(cs, start, end)); } else { for (int i = start; i < end; i++) { if (isOperator(cs[i])) { List<Integer> prev = diffWaysToCompute(cs, start, i); List<Integer> suff = diffWaysToCompute(cs, i + 1, end); result.addAll(combineResult(prev, suff, cs[i])); } } return result; } cache.put(key, result); return result; } private List<Integer> combineResult(List<Integer> prev, List<Integer> suff, char op) { List<Integer> result = new ArrayList<>(); for (int x : prev) { for (int y : suff) { result.add(calculate(x, y, op)); } } return result; } private int calculate(int x, int y, char op) { switch (op) { case ‘+‘: return x + y; case ‘-‘: return x - y; case ‘*‘: return x * y; } return 0; } private List<Integer> toNum(char[] cs, int start, int end) { int num = 0; for (int i = start; i < end; i++) { if (cs[i] == ‘ ‘) { continue; } num = num * 10 + (cs[i] - ‘0‘); } List<Integer> result = new ArrayList<>(1); result.add(num); return result; } private boolean isOperator(char c) { return c == ‘+‘ || c == ‘-‘ || c == ‘*‘; } public List<Integer> diffWaysToCompute(String input) { return diffWaysToCompute(input.toCharArray(), 0, input.length()); } public static void main(String[] args) { Solution solution = new Solution(); System.out.println(solution.diffWaysToCompute("2-4").stream().map(x -> "" + x).collect(Collectors.joining(","))); }
再仔细想想,这种需要cache之前结果的递归算法,应该是可以用动态规划的方式表达出来的。可惜我不擅长动态规划,就不费脑力了~~~
标签:
原文地址:http://my.oschina.net/u/922297/blog/484437