39. Combination Sum
题目:
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7]
and target 7
,
A solution set is:
[ [7], [2, 2, 3] ]
链接:https://leetcode.com/problems/combination-sum/#/description
4/14/2017
19ms, 84%
一种算法要是有了一个公式可以让之前不会的人生套进去,这是多么的伟大哈哈!我觉得自己可能以后不会下意识的害怕backtracking了,只是有些小细节需要注意。
注意的地方:
1. 第6行需要sort
2. 在enumerate函数中,我们需要传入pos,在sort之后再加pos,我们保证了元素至少都是按照升序(严格升序或者相同元素)来加入temp里面的。这点一开始我忽略了,导致了重复的结果。
3. 注意第18行跟普通的backtracking不一样,一般我们会用i+1,不过这里因为可以重复,所以还是用i作为pos
4. 特别重要的一点,第12行需要新建一个ArrayList,否则元素都在后面被remove了
1 public class Solution { 2 public List<List<Integer>> combinationSum(int[] candidates, int target) { 3 List<List<Integer>> ret = new ArrayList<>(); 4 if (candidates.length == 0) return ret; 5 List<Integer> temp = new ArrayList<Integer>(); 6 Arrays.sort(candidates); 7 enumerate(candidates, target, temp, ret, 0); 8 return ret; 9 } 10 private void enumerate(int[] candidates, int target, List<Integer> temp, List<List<Integer>> ret, int pos) { 11 if (target == 0) { 12 ret.add(new ArrayList<Integer>(temp)); 13 return; 14 } 15 for (int i = pos; i < candidates.length; i++) { 16 if (target < candidates[i]) break; 17 temp.add(candidates[i]); 18 enumerate(candidates, target - candidates[i], temp, ret, i); 19 temp.remove(temp.size() - 1); 20 } 21 } 22 }
别人的答案,他总结了常见的backtracking
还有iterative DP做法,不过我不准备研究了
https://discuss.leetcode.com/topic/8200/iterative-java-dp-solution
中间有人解释时间复杂度
https://github.com/Deadbeef-ECE/Interview/blob/master/Leetcode/BackTracking/039_Combination_Sum.java
更多讨论