给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
题解:这道题的解法与leetcode39(组合总和)基本上是一致的,只不过会多一个去重步骤,比如对于数组[2,2,3]和target:5,如果按照正常的回溯法,使用与leetcode39(组合总和)一样的解法会得到两个重复的答案[2,3]和[2,3],我们需要在回溯的过程中进行去重,最有效的去重方法是构造一个List容器,存储数组中出现的元素和该元素出现的次数,我们递归时不再递归原数组,而是构造的List容器,一个元素出现次数为n次,说明该元素可以被递归0到n次,也就是在一个解集数组中可以出现0到n次,我们只需要利用回溯枚举这0到n次,就可以得到所有结果,并且达到去重的目的
class Solution {
private final Stack<Integer>stack=new Stack<>();
private final List<List<Integer>>res=new ArrayList<>();
private final List<int[]>arrayElements=new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Solution.sort(candidates);
int repeat=1;
//构造List容器,存储数组中的元素及其出现次数
for(int i=0;i< candidates.length-1;i++){
if(candidates[i]==candidates[i+1])
repeat++;
else{
arrayElements.add(new int[]{
candidates[i],repeat});
repeat=1;
}
}
arrayElements.add(new int[]{
candidates[candidates.length-1],repeat});
backTrace(candidates,0,0,target);
return res;
}
private void backTrace(int[]candidates,int pos,int sum,int target){
if(sum==target)
res.add(new ArrayList<>(stack));
if(pos>=arrayElements.size())
return;
int element=arrayElements.get(pos)[0];
int repeat=arrayElements.get(pos)[1];
if(target-sum<element)
return;
//执行一次循环,则解集数组中出现一次该元素
for(int i=0;i<repeat;i++){
stack.push(element);
backTrace(candidates,pos+1,sum+element*(i+1),target);
}
for(int i=0;i<repeat;i++){
stack.pop();
}
//结果数组中没有该元素
backTrace(candidates,pos+1,sum,target);
}
//快排算法
public static void sort(int[]args){
quickSort(args,0,args.length-1);
}
private static void quickSort(int[]args,int start,int end){
if(start>=end)
return;
int pivot=args[start];
int left=start;
int right=end;
while(left<right){
while(args[right]>pivot&&left<right)
right--;
while(args[left]<=pivot&&left<right)
left++;
change(args,right,left);
}
change(args,start,left);
quickSort(args,start,left-1);
quickSort(args,left+1,end);
}
private static void change(int[]args,int x,int y){
int temp=args[x];
args[x]=args[y];
args[y]=temp;
}
}