給定一個正確的表達式(不用擔憂不規範的輸入),好比2-1-1, 經過在不一樣位置添加左右括號,改變求值的優先級順序,求出全部的這些值;java
Example 1算法
Input: "2-1-1"
.spa
((2-1)-1) = 0 (2-(1-1)) = 2
Output: [0, 2]
code
Example 2orm
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]
get
這個題目應該沒有便捷的解法,只能所有的都嘗試一遍;固然僅僅須要暴力的枚舉一遍,也沒有什麼有趣的地方,我以爲有趣的地方體如今下面兩點:input
1. 這個題目能夠用遞歸的方法求解,由於,假設遇到某個操做符,若是知道了左邊的結果,再計算出右邊的結果,那麼只要把左右兩邊的結果合併起來,就能夠了;it
2. 固然若是直接按照遞歸去作,會出現一個問題,(大概會超時,我沒有提交這樣的代碼);假設在獲得了某個操做符兩邊的結果後,到了下一個操做符,遞歸計算的時候,任然會須要前面一個操做符(左邊的)的結果,因此必需要把已經計算過的結果要cache起來;io
最後的代碼以下:
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以前結果的遞歸算法,應該是能夠用動態規劃的方式表達出來的。惋惜我不擅長動態規劃,就不費腦力了~~~