** 题目**:
39.组合总和I
40.组合总和II
** 思路**
从target开始,依次减去数组中的数,直到target<0或target==0,将等于0的结果,放到结果集当中。(也可从0开始相加)
这里的做法,有点树的前序遍历。
题目关键是去重。但两道题给的条件不一样,所以去重上有点区别。
39.重复原因:
解决: 设置搜索起点即可
40.题重复原因:
解决: 设置搜索起点+排序后,剪枝(因为数组中有重复数字)。
因为40题要求,所有数字只能取一次,所以搜索起点比上一层节点+1
** 代码**:
39题
```Java
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
if (candidates == null || candidates.length == 0 || target < 0) {
return result;
}
Arrays.sort(candidates);
backTrack(candidates, target, 0, new ArrayList<>(), result);
return result;
}
private void backTrack(int[] candidates, int target, int start, List<Integer> tem_list, List<List<Integer>> result) {
if (target < 0) {
return;
}
if (target == 0) {
result.add(new ArrayList<>(tem_list));
return;
}
for (int i = start; i < candidates.length; ++i) {
//剪枝
if (candidates[i] > target) {
break;
}
tem_list.add(candidates[i]);
backTrack(candidates, target - candidates[i], i , tem_list, result);
tem_list.remove(tem_list.size() - 1); //封装类型为引用传递
}
}
40题
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
if (candidates == null || candidates.length == 0 || target < 0) {
return result;
}
Arrays.sort(candidates);
backTrack(candidates, target, 0, new ArrayList<>(), result);
return result;
}
public static void backTrack(int[] candidates, int target, int start, List<Integer> tem_list, List<List<Integer>> result) {
if (target < 0) {
return;
}
if (target == 0) {
result.add(new ArrayList<>(tem_list));
return;
}
for (int i = start; i < candidates.length; ++i) {
//大剪枝
if (candidates[i] > target) {
break;
}
//小剪枝
if (i > start && candidates[i] == candidates[i - 1]) {
continue;
}
tem_list.add(candidates[i]);
backTrack(candidates, target - candidates[i], i + 1, tem_list, result);
tem_list.remove(tem_list.size() - 1); //封装类型为引用传递
}
}