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:
1) All numbers (including target) will be positive integers.
2) Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
3) The solution set must not contain duplicate combinations.
Java Solution
This problem is an extension of Combination Sum. The difference is one number in the array can only be used ONCE.
public List<List<Integer>> combinationSum2(int[] candidates, int target) { List<List<Integer>> result = new ArrayList<List<Integer>>(); List<Integer> curr = new ArrayList<Integer>(); Arrays.sort(candidates); helper(result, curr, 0, target, candidates); return result; } public void helper(List<List<Integer>> result, List<Integer> curr, int start, int target, int[] candidates){ if(target==0){ result.add(new ArrayList<Integer>(curr)); return; } if(target<0){ return; } int prev=-1; for(int i=start; i<candidates.length; i++){ if(prev!=candidates[i]){ // each time start from different element curr.add(candidates[i]); helper(result, curr, i+1, target-candidates[i], candidates); // and use next element only curr.remove(curr.size()-1); prev=candidates[i]; } } } |
We can literally use the same solution from Combination Sum I with just two slight modifications. One in the helper recursive call with i+1 and the other when sum==target to check if the list exists in result or not.
class Solution {
public List<List> combinationSum2(int[] candidates, int target) {
List<List> result = new ArrayList();
List temp = new ArrayList();
Arrays.sort(candidates);
helper(candidates,0,target,0,temp,result);
return result;
}
private void helper(int[] candidates, int start, int target, int sum, List list, List<List> result){
if(sum > target){
return;
}
if(sum == target){
Iterator i = result.iterator();
int flag=0;
while(i.hasNext()){
if(list.equals(i.next())){
flag=1;
}
}
if(flag==0)
result.add(new ArrayList(list));
return;
}
else{
for(int i=start;i<candidates.length;i++){
list.add(candidates[i]);
helper(candidates,i+1,target,sum+candidates[i],list,result);
list.remove(list.size()-1);
}
}
}
}
Another variation
public class Solution {
public IList<IList> CombinationSum2(int[] candidates, int target)
{
if (candidates == null || candidates.Length == 0)
return null;
var result = new List<IList>();
List temp = new List();
Array.Sort(candidates);
DFS(candidates, target, 0, result, temp, 0);
return result;
}
public void DFS(int[] candidates, int target, int startIndex, List<IList> results, List temp, int sum)
{
if (sum > target)
return;
if (sum == target)
{
List tempResult = new List(temp);
results.Add(tempResult);
return;
}
for (int i = startIndex; i < candidates.Length; i++)
{
temp.Add(candidates[i]);
sum += candidates[i];
DFS(candidates, target, i+1, results, temp, sum);
while (i + 1 < candidates.Length && candidates[i] == candidates[i + 1])
{
i++;
}
sum -= candidates[i];
temp.Remove(candidates[i]);
}
}
}