给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
例:
输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
题解:快排+回溯,对于枚举+组合的问题,我们都可以用回溯法进行解决,这道题只不过是给枚举法的枚举结果增加了筛选限制——使枚举组合中的数字加起来等于target。我们只需要在回溯的过程中,判断当前所有数字和等于target。在运用回溯法时,我们用到快排给数组排序,使回溯更加有序。
class Solution {
private final Stack<Integer>stack=new Stack<>();
private final List<List<Integer>>res=new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Solution.sort(candidates);
backTrace(candidates,target,0,0);
return res;
}
//回溯算法进行枚举+组合
private void backTrace(int[]candidates,int target,int min,int sum){
if(sum==target)
res.add(new ArrayList<>(stack));
else if(target-sum<candidates[min])
return;
int len=candidates.length;
for(int i=min;i<len;i++){
if(sum+candidates[i]<=target) {
stack.push(candidates[i]);
backTrace(candidates,target,i,sum+candidates[i]);
stack.pop();
}
else
return;
}
}
//快排算法
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;
}
}