给出一组候选数字(C)和目标数字(T),找出C中所有的组合,使组合中数字的和为T。C中每个数字在每个组合中只能使用一次。
您在真实的面试中是否遇到过这个题?
Yes
样例
给出一个例子,候选数字集合为[10,1,6,7,2,1,5] 和目标数字 8 ,
解集为:[[1,7],[1,2,5],[2,6],[1,1,6]]
注意
- 所有的数字(包括目标数字)均为正整数。
- 元素组合(a1, a2, … , ak)必须是非降序(ie, a1 ≤ a2 ≤ … ≤ ak)。
- 解集不能包含重复的组合。
解题思路:
十分普通的回溯算法,每个组合中每个数字只能用一次,选择一个LIST,每次去掉该数,回溯时候将其加上。
public class Solution {
/**
* @param num: Given the candidate numbers
* @param target: Given the target number
* @return: All the combinations that sum to target
*/
@SuppressWarnings("unchecked")
public List<List<Integer>> combinationSum2(int[] num, int target) {
// write your code here
List<List<Integer>> res = new ArrayList<>();
if(num==null||0==num.length) return res;
ArrayList<Integer> tmp = new ArrayList<>();
List<Integer> canList = new ArrayList<>();
for(int i=0;i<num.length;i++){
canList.add(num[i]);
}
combinationSUm(canList, target, res, tmp);
return res;
}
@SuppressWarnings("unchecked")
public void combinationSUm(List<Integer> canList,int target,List<List<Integer>> res,ArrayList<Integer> tmp){
if(target<0) return ;
if(target==0){
List<Integer> tmpItem = (List<Integer>) tmp.clone();
Collections.sort(tmpItem);
if(!res.contains(tmpItem)){
res.add(tmpItem);
}
return;
}
for(int i=0;i<canList.size();i++){
int canItem = canList.get(i);
target -= canItem;
tmp.add(canItem);
canList.remove(i);
combinationSUm(canList, target, res, tmp);
target += canItem;
tmp.remove(tmp.size()-1);
canList.add(i,canItem);
}
}
}
方法2:
先排序,然后去进行递归回溯
public class Solution {
private ArrayList<ArrayList<Integer>> results;
public ArrayList<ArrayList<Integer>> combinationSum2(int[] candidates,
int target) {
if (candidates.length < 1) {
return results;
}
ArrayList<Integer> path = new ArrayList<Integer>();
java.util.Arrays.sort(candidates);
results = new ArrayList<ArrayList<Integer>> ();
combinationSumHelper(path, candidates, target, 0);
return results;
}
private void combinationSumHelper(ArrayList<Integer> path, int[] candidates, int sum, int pos) {
if (sum == 0) {
results.add(new ArrayList<Integer>(path));
}
if (pos >= candidates.length || sum < 0) {
return;
}
int prev = -1;
for (int i = pos; i < candidates.length; i++) {
if (candidates[i] != prev) {
path.add(candidates[i]);
combinationSumHelper(path, candidates, sum - candidates[i], i + 1);
prev = candidates[i];
path.remove(path.size()-1);
}
}
}
}