题目描述
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
- 所有数字(包括 target)都是正整数。
- 解集不能包含重复的组合。
示例 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]
]
思路分析
回溯问题。三要素。dfs+剪枝。
路径:已经加入的数字。
选择列表:还能选择加入的数字。
结束条件:sum==target;sum > target。
这种写法还能继续优化,比如2,2,2,2 > 7,则后续的2223,2226,2227都可以不用进入函数,直接跳出。
代码实现
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> lists = new ArrayList<>();
if (candidates == null || candidates.length == 0) {
return lists;
}
if (candidates == null || candidates.length == 0 || target == 0) {
return lists;
}
process(candidates, target, lists, 0, new ArrayList<>(), 0);
return lists;
}
public void process(int[] candidates, int target, List<List<Integer>> lists, int sum, List<Integer> list, int i) {
if (sum > target || i > candidates.length - 1) {
return;
}
if (sum == target) {
lists.add(new ArrayList<>(list));
}
//这里还能继续优化,比如2222超出,后面就不用再继续2223,2226,因为必然超出
for (int j = i; j < candidates.length; j++) {
sum += candidates[j];
list.add(candidates[j]);
process(candidates, target, lists, sum, list, j);
list.remove(list.lastIndexOf(candidates[j]));
sum -= candidates[j];
}
}