組合總和 II
題目描述:給定一個陣列 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。
candidates 中的每個數字在每個組合中只能使用一次。
說明:
- 所有數字(包括目標數)都是正整數。
- 解集不能包含重複的組合。
示例說明請見LeetCode官網。
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/probl...
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
解法一:回溯演算法
- 首先,將原陣列排序;
- 然後,宣告一個陣列freq用來記錄每個不同的數字出現的次數;
- 然後,用回溯演算法遞迴判斷處理的序列是否符合條件,將符合條件的序列新增到結果集中,最後返回所有符合條件的結果集。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LeetCode_040 {
/**
* 記錄每個不同的數字出現的次數
*/
private static List<int[]> freq = new ArrayList<>();
/**
* 符合條件的結果集
*/
private static List<List<Integer>> ans = new ArrayList<>();
/**
* 匹配的序列
*/
private static List<Integer> sequence = new ArrayList<>();
/**
* 回溯演算法
*
* @param candidates
* @param target
* @return
*/
public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
// 首先將給定的陣列排序
Arrays.sort(candidates);
for (int num : candidates) {
int size = freq.size();
if (freq.isEmpty() || num != freq.get(size - 1)[0]) {
freq.add(new int[]{num, 1});
} else {
++freq.get(size - 1)[1];
}
}
dfs(0, target);
return ans;
}
public static void dfs(int pos, int rest) {
if (rest == 0) {
/**
* 如果當前的和已經等於target了,將當前的序列新增到結果集
*/
ans.add(new ArrayList<Integer>(sequence));
return;
}
if (pos == freq.size() || rest < freq.get(pos)[0]) {
/**
* 如果已經遍歷完所有的數字或者待處理的數小於下一個要匹配的數字,則當前的序列不符合條件,返回
*/
return;
}
dfs(pos + 1, rest);
int most = Math.min(rest / freq.get(pos)[0], freq.get(pos)[1]);
for (int i = 1; i <= most; ++i) {
sequence.add(freq.get(pos)[0]);
dfs(pos + 1, rest - i * freq.get(pos)[0]);
}
for (int i = 1; i <= most; ++i) {
sequence.remove(sequence.size() - 1);
}
}
public static void main(String[] args) {
int[] candidates = new int[]{10, 1, 2, 7, 6, 1, 5};
for (List<Integer> integers : combinationSum2(candidates, 8)) {
for (Integer integer : integers) {
System.out.print(integer + " ");
}
System.out.println();
}
}
}
【每日寄語】 登高望遠,不是為了被整個世界看到,而是為了看到整個世界。