重複する要素のない候補の配列とターゲット数のターゲットが与えられた場合、数の合計をターゲットにすることができる候補のすべての組み合わせを見つけます。
候補の数は制限なく繰り返し選択できます。
例:
入力:候補= [2,3,6,7]、ターゲット= 7、
ソリューションセット:
[
[7]、
[2,2,3]
]
問題の解決策:高速ソート+バックトラッキング。列挙+組み合わせの問題では、すべての問題を解決するためにバックトラッキングメソッドを使用できます。この問題は、列挙メソッドの列挙結果にフィルタリング制限を追加することで、列挙の組み合わせを作成します。数値はターゲットに加算されます。現在のすべての数値の合計がバックトラックのプロセスでのターゲットに等しいことを確認するだけで済みます。バックトラッキング方式を使用する場合は、高速ソートを使用して配列をソートし、バックトラッキングをより規則的にします。
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;
}
}