[LintCode] Add Operators
Given a string that contains only digits 0
-9
and a target value, return all possibilities to add binary operators (not unary) +
, -
, or *
between the digits so they evaluate to the target value.
"123", 6 -> ["1+2+3", "1*2*3"]
"232", 8 -> ["2*3+2", "2+3*2"]
"105", 5 -> ["1*0+5","10-5"]
"00", 0 -> ["0+0", "0-0", "0*0"]
"3456237490", 9191 -> []
1 public class Solution { 2 public List<String> addOperators(String num, int target) { 3 List<String> results = new ArrayList<String>(); 4 if(num == null || num.length() == 0) { 5 return results; 6 } 7 List<List<Integer>> integerLists = new ArrayList<>(); 8 enumerateIntegerLists(integerLists, new ArrayList<Integer>(), num, 0); 9 for(List<Integer> integers : integerLists) { 10 enumerateOperators(results, integers, new ArrayList<String>(), integers.get(0), integers.get(0), target, 1); 11 } 12 return results; 13 } 14 private void enumerateIntegerLists(List<List<Integer>> integerLists, List<Integer> integers, 15 String num, int startIdx) { 16 if(startIdx == num.length()) { 17 integerLists.add(new ArrayList<Integer>(integers)); 18 return; 19 } 20 int currNum = num.charAt(startIdx) - '0'; 21 integers.add(currNum); 22 enumerateIntegerLists(integerLists, integers, num, startIdx + 1); 23 integers.remove(integers.size() - 1); 24 if(currNum != 0){ 25 for(int i = startIdx + 1; i < num.length(); i++) { 26 currNum = currNum * 10 + num.charAt(i) - '0'; 27 integers.add(currNum); 28 enumerateIntegerLists(integerLists, integers, num, i + 1); 29 integers.remove(integers.size() - 1); 30 } 31 } 32 } 33 private void enumerateOperators(List<String> results, List<Integer> integers, List<String> operators, 34 int currSum, int lastFactor, int target, int currIdx) { 35 if(currIdx == integers.size()) { 36 if(currSum == target) { 37 results.add(constructFormula(integers, operators)); 38 } 39 return; 40 } 41 int newSum = 0, newLastFactor = 0; 42 43 operators.add("+"); 44 newSum = currSum + integers.get(currIdx); 45 newLastFactor = integers.get(currIdx); 46 enumerateOperators(results, integers, operators, newSum, newLastFactor, target, currIdx + 1); 47 operators.remove(operators.size() -1); 48 49 operators.add("-"); 50 newSum = currSum - integers.get(currIdx); 51 newLastFactor = 0 - integers.get(currIdx); 52 enumerateOperators(results, integers, operators, newSum, newLastFactor, target, currIdx + 1); 53 operators.remove(operators.size() -1); 54 55 operators.add("*"); 56 newSum = currSum - lastFactor + lastFactor * integers.get(currIdx); 57 newLastFactor = lastFactor * integers.get(currIdx); 58 enumerateOperators(results, integers, operators, newSum, newLastFactor, target, currIdx + 1); 59 operators.remove(operators.size() -1); 60 } 61 private String constructFormula(List<Integer> integers, List<String> operators) { 62 StringBuilder sb = new StringBuilder(); 63 sb.append(integers.get(0)); 64 for(int i = 0; i < operators.size(); i++) { 65 sb.append(operators.get(i)); 66 sb.append(integers.get(i + 1)); 67 } 68 return sb.toString(); 69 } 70 }
Solution 2.
The recursive call dfs() is the core here.
void dfs(int pos, String str, long sum, long lastF):
The output condition is that we've used all digits(pos == num.length()) and the current sum equals to target(sum == target).
The functionality of this dfs is: Given the partial result string, current Sum sum and lastFactor lastF from dfs to num[0.......pos - 1],
and starting from index pos, enumerate one number that starts at index pos, the do the following.
a. If this is the first number(pos == 0), then add this number to the string and make a recursive call starting from the next unused index.
b. If this is not the first number(pos != 0), then update current sum and lastFactor accordingly and make 3 recursive calls starting from the next unused index, each call is for one of the 3 operators.
As long as the number at starting index pos is not 0, we repeat a && b until we've reached the end of the digits string; This is done by line 13.
Otherwise, we know that if we include more digits we would have numbers with leading 0. Skip all the rest cases.
1 public class Solution { 2 String num; 3 int target; 4 List<String> ans = new ArrayList<>(); 5 6 void dfs(int pos, String str, long sum, long lastF) { 7 if (pos == num.length()) { 8 if (sum == target) { 9 ans.add(str); 10 } 11 return; 12 } 13 for (int i = pos; i < num.length(); i++) { 14 long cur = Long.parseLong(num.substring(pos, i + 1)); 15 16 if (pos == 0) { 17 dfs(i + 1, "" + cur, cur, cur); 18 } else { 19 dfs(i + 1, str + "*" + cur, sum - lastF + lastF * cur, lastF * cur); 20 dfs(i + 1, str + "+" + cur, sum + cur, cur); 21 dfs(i + 1, str + "-" + cur, sum - cur, -cur); 22 } 23 if (num.charAt(pos) == '0') { 24 break; 25 } 26 } 27 } 28 public List<String> addOperators(String num, int target) { 29 this.num = num; 30 this.target = target; 31 dfs(0, "", 0, 0); 32 return ans; 33 } 34 }