要求:
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。 说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
思路:
- 递归加回溯剪枝
- 先创建一个全局变量
List<List<Integer>>用来最后将其返回。 - 对特殊情况进行判断,什么时候直接返回
- 创建新的辅助记录的
List<Integer> - 递归
- 返回结果 递归:
- 先写递归终止条件:
target<0就直接返回;target==0就添加元素进辅助列表 - 正常情况下就进入循环:
- 先把元素这一轮的元素添加进去
- 是从前往后加的,target做减法,每个数字都可以用s无数次,所以递归可以从当前元素开始
- 循环的最后需要剪枝,就是把每次最新添加的数删除,不然会导致数字一直累加。
代码:
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);//对数组进行排序,防止出现重复时无法有效剪枝
List<Integer> list = new ArrayList<>();
if (candidates.length == 0 || candidates == null || candidates[0] > target) return res;
dfs(0, candidates, target, list);
return res;
}
public void dfs(int i, int[] nums, int sum, List<Integer> list) {//起始索引,数组,和,辅助列表
if(sum < 0) return;
if(sum == 0) res.add(new ArrayList<>(list));
else {
for(int j = i; j < nums.length; j++) {
list.add(nums[j]);
dfs(j, nums, sum-nums[j], list);
list.remove(list.size()-1);
}
}
}
}