Problem 1: Combination Sum I
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]
分析:
很像传统的硬币问题,我们同样运用Subset和Permutation的思路,只需要考虑两个问题:
1. 什么时候返回?
2. 递归的时候传入什么样的参数
对于上面第二点,我们不妨可以这么想,如果现在和为Target,此时取一个硬币,假设其值为v1,那么下一次,我们其实解决的是相同的子问题,只不过和变成了Target - v1 既然明确了第二点,我们就可以通过Target的取值来确定返回条件
1. 当Target < 0 的时候,无解,return
2. 当Target == 0 的时候,发现解,添加进res里面,然后return
代码如下:
public class Solution {
public ArrayList<ArrayList<Integer>> combinationSum(int[] candidates, int target) {
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> tmp = new ArrayList<Integer>();
Arrays.sort(candidates);
dfs(res,tmp,candidates,target,0);
return res;
}
public void dfs(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> tmp, int[] cand, int target, int pos){
if(target<0) return;
if(target==0){
res.add(new ArrayList<Integer>(tmp));
return;
}
for(int i=pos; i<cand.length; i++){
tmp.add(cand[i]);
dfs(res,tmp,cand,target-cand[i],i);
tmp.remove(tmp.size()-1);
}
}
}
需要注意的几点问题:
1.如果不用pos,从数组开头往数组尾巴扫,会出现什么问题? 会出现重复集合的问题,这里的重复不是指顺序完全相同的Set,而是对于每一种组合,我们输出一次就可以了 比如Sum = 3 不加pos会出现 [1,2],[2,1]两种一样的解,我们加入一个pos,限制每次添加只能再添加和这个数字相等或者比这个数字大的数字(数组之前sort过升序排列)这样就会避免问题
Problem 2 : Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. Each number in C may only be used once in the combination.
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 10,1,2,7,6,1,5 and target 8, A solution set is: [1, 7] [1, 2, 5] [2, 6] [1, 1, 6]
同样的思路,只需要注意几个问题:
1. 每个数字只能运用1次,所以再调用dfs的时候,传入的pos,应该是i + 1
2. 利用同样的思路来防止有重复的Set
while(i<num.length-1&&num[i]==num[i+1]) i++;
代码如下:
public class Solution {
public ArrayList<ArrayList<Integer>> combinationSum2(int[] num, int target) {
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> tmp = new ArrayList<Integer>();
Arrays.sort(num);
dfs(res,tmp,num,target,0);
return res;
}
public void dfs(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> tmp, int[] num, int target, int pos){
if(target<0) return;
if(target==0){
res.add(new ArrayList<Integer>(tmp));
return;
}
for(int i=pos; i<num.length;i++){
tmp.add(num[i]);
dfs(res,tmp,num,target-num[i],i+1);
tmp.remove(tmp.size()-1);
while(i<num.length-1&&num[i]==num[i+1]) i++;
}
}
}