给定一个数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 :
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
思路:
- 与题39类似,做出些小的改动,点击蓝字查看
- 不同之处在于,无法自身遍历,同时需要做解集去重处理
代码:
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
int len = candidates.length;
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
if (len == 0)
return res;
// 先排个序
Arrays.sort(candidates);
combinationSumHelp2(res, list, candidates, target, 0);
return res;
}
private boolean combinationSumHelp2(List<List<Integer>> res, List<Integer> list, int[] candidates, int target,
int start) {
// 对减去后的target值进行判断,
if (target < 0)
return false;
else if (target == 0) {
// list对象一直处于变动中,不能直接导入list对象,
List<Integer> temp = new ArrayList<>(list);
res.add(temp);
return false;
} else {
for (int i = start; i < candidates.length; i++) {
// 跳过相同数字,防止出现重复集合
if (i > start && candidates[i] == candidates[i - 1])
continue;
list.add(candidates[i]);
// 深度优先遍历,就像一只深入地底的探测器
// 使i增加1,去除自身遍历
boolean flag = combinationSumHelp(res, list, candidates, target - candidates[i], i + 1);
list.remove(list.size() - 1);
// 此路不通时,由于排序后的数组,i之后数字只能更大,跳出循环
if (!flag)
break;
}
}
return true;
}
总结:
- 借用
for
循环去重, - 注意优化递归方法中的代码
- 详情见蓝字