我直观的思路是揹包客问题。这是一道变种的完全揹包客问题,完全揹包客问题是,用一定容量的揹包去装每种数量不限的具有特定价值和特定重量的金块。
但是速度上很慢。看网友的解法,换用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();
}
}
}