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]
Have you been asked this question in an interview?
dfs method
public class Solution {
public List<List<Integer>> combinationSum2(int[] num, int target) {
List<List<Integer> > combs = new ArrayList<List<Integer>>();
Arrays.sort(num);
int len = num.length;
List<Integer> oneSolution = new ArrayList<Integer>();
if(len > 0 && target > 0)
dfs(combs, oneSolution, 0, num, 0, target);
return combs;
}
private void dfs(List<List<Integer> > combs, List<Integer> oneSolution, int start, int[] num, int sum, int target){
if(sum > target) return; // can not be a solution
if(sum == target){
List<Integer> temp = new ArrayList<Integer>();
temp.addAll(oneSolution);
combs.add(temp);
return; //can not do dfs further for this case
}
for(int i = start; i < num.length; ++i) {
sum += num[i];
oneSolution.add(num[i]);
dfs(combs, oneSolution, i + 1, num, sum, target); //once it finished, we do next dfs
sum -= num[i];
oneSolution.remove(oneSolution.size() - 1);
//since we have finished the dfs starting with index num[start]
//if there are same number in num, we need to skip dfs for them
while(i < num.length - 1 && num[i] == num[i + 1])
++i;
//i stops at the last element such that num[i] == num[start]
}
}
}
another code
public class Solution {
public ArrayList<ArrayList<Integer>> combinationSum2(int[] num, int target) {
List<List<Integer> > result = new ArrayList<List<Integer> >();
Arrays.sort(num);
int len = num.length;
if(len > 0 && num[0] <= target){
ArrayList<ArrayListWithSum> alist = new ArrayList<ArrayListWithSum>();
alist.add(new ArrayListWithSum(new ArrayList<Integer>(), 0));
int index = 0;
while(index < len && !alist.isEmpty()){
ArrayList<ArrayListWithSum> temp = new ArrayList<ArrayListWithSum>();
int theSame = checkSame(num, index);
while(!alist.isEmpty()){
ArrayListWithSum temp1 = alist.remove(0);
ArrayList<Integer> toBeAdded = new ArrayList<Integer>();
for(int j = 0; j < theSame - index + 1; ++j){
ArrayList<Integer> templist = new ArrayList<Integer>();
templist.addAll(temp1.li);
templist.addAll(toBeAdded);
if(temp1.sum + j * num[index] < target)
temp.add(new ArrayListWithSum(templist, temp1.sum + j * num[index]));
else if(temp1.sum + j * num[index] == target)
result.add(templist);
toBeAdded.add(num[index]);
}
}
alist = temp;
index = theSame;
}
}
return result;
}
public static int checkSame(int[] arr, int i){
int len = arr.length;
int j = i;
for(; j < len; ++j){
if(arr[j] != arr[i])
break;
}
return j;
}
}
class ArrayListWithSum{
ArrayList<Integer> li;
int sum;
ArrayListWithSum(ArrayList<Integer> li, int sum){
this.li = li;
this.sum = sum;
}
}