給定一個數組,candidates和一個目標數target, 找出candidates中的每個數字,在每個組合中只能使用一次。
說明:
1.所有數字(包括目標數)都是正整數。
2.解集不能包含重複的組合。
示例1:
輸入:cadidates = [10 1 2 7 6 1 5],target = 8
所求的解集是:
[[1,7],[1,2,5],[2,6],[1,1,6]]
示例2:
輸入:cadidates = [2 5 2 1 2], target = 5
所求解集是:[1,2,2],[5]
解題思路:
窮舉類問題想到回溯法。
1)排序,我們先看看一下排序的效果
如cadidates = [10,1,2,7,6,1,5],target = 8
排序後cadidates = [1,1,2,5,6,7,10] ,假設做到1 + 1 + 2,下一步+5已經大於5了,因此這種情況後的所有組合都可以跳過不做,如果不排序是達不到這個效果的。
2)去重的問題,另一個思路是用一個HashSet<List> ,每次判斷set是否已經包含即將添加的list.
代碼:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class CombinationSum_1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入數組個數: ");
int n = scanner.nextInt();
System.out.println("請輸入數組: ");
int [] num = new int[n];
for (int i = 0; i < num.length; i++) {
num[i] = scanner.nextInt();
}
System.out.println("請輸入目標數: ");
int target = scanner.nextInt();
List<List<Integer>> lists = new CombinationSum_1().combinationSum2(num,target);
System.out.println(lists);
}
List<List<Integer>> lists = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if (candidates == null || candidates.length == 0) {
return null;
}
Arrays.sort(candidates);
findList(candidates,target,0,0,new ArrayList<>());
return lists;
}
public void findList(int[] candidate,int target,int sum,int index,List<Integer> list){
if (sum == target){
lists.add(new ArrayList<>(list));
return;
}else {
for (int i = index; i < candidate.length ; i++) {
if (i > index && candidate[i] == candidate[i - 1]) continue;
if (sum + candidate[i] <= target){
list.add(candidate[i]);
findList(candidate,target,sum+candidate[i],i+1,list);
list.remove(list.size() - 1);
}
}
}
}
}