做题博客链接
https://blog.youkuaiyun.com/qq_43349112/article/details/108542248
题目链接
https://leetcode-cn.com/problems/combination-sum/
描述
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target
的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
提示:
1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每个元素都是独一无二的。
1 <= target <= 500
示例
示例 1:
输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
初始代码模板
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
}
}
代码
一开始,可以只进行基本的剪支,并且由于没有重复值,不必用Set进行去重
class Solution {
List<List<Integer>> res;
LinkedList<Integer> tmp;
public List<List<Integer>> combinationSum(int[] cs, int target) {
res = new ArrayList<>();
tmp = new LinkedList<>();
dfs(cs, target, 0);
return res;
}
private void dfs(int[] cs, int target, int idx) {
if (target == 0) {
res.add(new ArrayList<>(tmp));
return;
}
if (idx >= cs.length || target < 0) {
return;
}
//跳过当前元素
dfs(cs, target, idx + 1);
tmp.add(cs[idx]);
//选取当前元素
dfs(cs, target - cs[idx], idx);
tmp.removeLast();
}
}
再进行个排序,剪支可以提速一下。代码改动不大
class Solution {
List<List<Integer>> res;
LinkedList<Integer> tmp;
public List<List<Integer>> combinationSum(int[] cs, int target) {
res = new ArrayList<>();
tmp = new LinkedList<>();
Arrays.sort(cs);
dfs(cs, target, 0);
return res;
}
private void dfs(int[] cs, int target, int idx) {
if (target == 0) {
res.add(new ArrayList<>(tmp));
return;
}
if (idx >= cs.length || target < cs[idx]) {
return;
}
//跳过当前元素
dfs(cs, target, idx + 1);
tmp.add(cs[idx]);
//选取当前元素
dfs(cs, target - cs[idx], idx);
tmp.removeLast();
}
}