原题链接在这里:https://leetcode.com/problems/combination-sum/
题目:
Given a set of candidate numbers (C) 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.
- Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
- 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]
题解:
本题与Combinations, Permutations, N-Queens都是backtracking.
dfs时, target减掉candidates里一个数,然后递归调用helper, target设成target - candidates[i]. recursion终止条件是target == 0, 加入item的copy, target < 0说明已经减多了,直接return.
backtracking时恢复原貌.
题目中说要从小到大, 所以candidates的排序.
candidates里可能有duplicate, 所以需要去重.
Time Complexity: exponential.
Space: O(size). res中最长item的size是recursion的stack space.
AC Java:
1 public class Solution { 2 public List<List<Integer>> combinationSum(int[] candidates, int target) { 3 List<List<Integer>> res = new ArrayList<List<Integer>>(); 4 if(candidates == null || candidates.length == 0){ 5 return res; 6 } 7 Arrays.sort(candidates); 8 helper(candidates, target, 0, new ArrayList<Integer>(), res); 9 return res; 10 } 11 12 private void helper(int[] candidates, int target, int start, List<Integer> item, List<List<Integer>> res){ 13 if(target == 0){ 14 //去重 15 if(!res.contains(item)){ 16 res.add(new ArrayList<Integer>(item)); 17 } 18 return; 19 } 20 if(target < 0){ 21 return; 22 } 23 24 for(int i = start; i<candidates.length; i++){ 25 item.add(candidates[i]); 26 helper(candidates, target-candidates[i], i, item, res); 27 item.remove(item.size()-1); 28 } 29 } 30 }
去重也可以在循环中加入if(i>0 && candidates[i] == candidates[i-1]) continue; 是因为本题允许使用重复元素,若后面元素相同则不能再进行此验算。并且起到了去重的作用,就不用眼看res中是否已有item了.
e.g. 若是candidates = [1,1,2], target 是 3, 则会返回多组 [1,1,1].
AC Java:
1 public class Solution { 2 public List<List<Integer>> combinationSum(int[] candidates, int target) { 3 List<List<Integer>> res = new ArrayList<List<Integer>>(); 4 if(candidates == null || candidates.length == 0){ 5 return res; 6 } 7 Arrays.sort(candidates); 8 helper(candidates,target,0,new ArrayList<Integer>(),res); 9 return res; 10 } 11 private void helper(int[] candidates, int target, int start, List<Integer> item, List<List<Integer>> res){ 12 if(target == 0){ 13 res.add(new ArrayList<Integer>(item)); 14 return; 15 } 16 if(target < 0){ 17 return; 18 } 19 for(int i = start; i<candidates.length; i++){ 20 //这里可以使用重复元素,所以若是下一个元素与之前元素相同则没有必要对下一个元素进项判断,浪费时间 21 if(i>start && candidates[i] == candidates[i-1]){ 22 continue; 23 } 24 item.add(candidates[i]); 25 helper(candidates,target-candidates[i],i,item,res); 26 item.remove(item.size()-1); 27 } 28 } 29 }
跟上Combination Sum II, Combination Sum III, Combination Sum IV.