我直觀的思路是揹包客問題。這是一道變種的完全揹包客問題,完全揹包客問題是,用一定容量的揹包去裝每種數量不限的具有特定價值和特定重量的金塊。
但是速度上很慢。看網友的解法,換用dfs,深度優先遍歷的方法,配合剪枝操作。
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
// 無限揹包問題。
List<List<Integer>>[] res = new List[target + 1];// 存儲結果
for (int i = 0; i < target + 1; i++) {
res[i] = new LinkedList<>();
}
// 遍歷這些金子。
for (int i = 0; i < candidates.length; i++) {
int value = candidates[i];// 第i個金子的重量。
if (value > target) {
continue;
}
// value <= target 從value開始進行遍歷。
LinkedList<Integer> tmp = new LinkedList<Integer>();
tmp.add(value);
res[value].add(tmp);
for (int j = value + 1; j <= target; j++) {
if (res[j - value].size() != 0) {
List<List<Integer>> ago = res[j - value];
for (List<Integer> integers : ago) {
LinkedList<Integer> add = new LinkedList<>(integers);
add.add(value);
res[j].add(add);
}
}
}
}
return res[target];
}
}
深度優先遍歷,配合剪枝操作。速度有所提升。
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> res = new LinkedList<>();
int begin = 0;
int len = candidates.length;
LinkedList<Integer> path = new LinkedList<>();
dfs(candidates, target, begin, len, res, path);
return res;
}
private void dfs(int[] candidates,
int target,
int begin,
int len,
List<List<Integer>> res,
LinkedList<Integer> path) {
if (target == 0) {
res.add(new LinkedList<>(path));
return;
}
for (int i = begin; i < len; i++) {
if (candidates[i] > target) {
return;
}
path.add(candidates[i]);
dfs(candidates, target - candidates[i], i, len, res, path);
path.removeLast();
}
}
}
但是不配合剪枝操作,發現速度又提升了,這個現象的原因可能是不需要將數組進行排序造成的。
public class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
//Arrays.sort(candidates);
List<List<Integer>> res = new LinkedList<>();
int begin = 0;
int len = candidates.length;
LinkedList<Integer> path = new LinkedList<>();
dfs(candidates, target, begin, len, res, path);
return res;
}
private void dfs(int[] candidates,
int target,
int begin,
int len,
List<List<Integer>> res,
LinkedList<Integer> path) {
if (target < 0) return;
if (target == 0) {
res.add(new LinkedList<>(path));
return;
}
for (int i = begin; i < len; i++) {
// if (candidates[i] > target) {
// return;
// }
path.add(candidates[i]);
dfs(candidates, target - candidates[i], i, len, res, path);
path.removeLast();
}
}
}