难度中等485
给定一个数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。
说明:
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
示例 1:
输入: candidates =[10,1,2,7,6,1,5]
, target =8
, 所求解集为: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5, 所求解集为: [ [1,2,2], [5] ]
方法1:递归回溯,剪枝,参考39,使用set去重即可。
解答成功:
执行耗时:2098 ms,击败了5.03% 的Java用户
内存消耗:39.3 MB,击败了5.02% 的Java用户
class Solution {
//使用hashset去重
HashSet<List<Integer>> res = new HashSet<>();
public void func(int i,int nums[],List<Integer> sub_list,int target){
//判断sub_list目标数是否达到目标 或者 超出target 则返回
if(target==0){
res.add(sub_list);
return;
}else if(target<0){
return;
}
//递归条件不超过总长度
if(i==nums.length) return;
//for循环是在对每一个值都进行一次所有值筛选的递归
//j==i的目的是:i前面的数递归已经处理考虑过后面的数了,所以当前位置不需要考虑之前的数了
for (int j = i; j < nums.length; j++) {
List<Integer> new_list = new ArrayList<>(sub_list);
new_list.add(nums[j]);
if(target-nums[j]<0) break;//剪枝,因为已经排序了,当前的数已经超过目标值了,后面的没必要再选了
//不重复选择当前值计算
func(j+1, nums,new_list,target-nums[j]);
}
}
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);//剪枝需要的前提
func(0, candidates, new ArrayList<>(), target);
//将hashset转换成arrayllist
return new ArrayList<List<Integer>>(res);
}
}
方法2:
解答成功:
执行耗时:3 ms,击败了81.49% 的Java用户
内存消耗:38.6 MB,击败了75.90% 的Java用户
class Solution {
List<List<Integer>> res = new ArrayList<>();
public void func(int i,int nums[],List<Integer> sub_list,int target){
//判断sub_list目标数是否达到目标 或者 超出target 则返回
if(target==0){
res.add(sub_list);
return;
}else if(target<0){
return;
}
//递归条件不超过总长度
if(i==nums.length) return;
//for循环是在对每一个值都进行一次所有值筛选的递归
//j==i的目的是:i前面的数递归已经处理考虑过后面的数了,所以当前位置不需要考虑之前的数了
for (int j = i; j < nums.length; j++) {
List<Integer> new_list = new ArrayList<>(sub_list);
new_list.add(nums[j]);
if(target-nums[j]<0) break;//剪枝,因为已经排序了,当前的数已经超过目标值了,后面的没必要再选了
//小剪枝,同一层相同的数进行剪枝
//j>i:确保每次的第一个值一定能处理到
//nums[j]==nums[j-1],处理相邻的相同的数,只保留第一个
if(j>i&&nums[j]==nums[j-1]) continue;
//不重复选择当前值计算
func(j+1, nums,new_list,target-nums[j]);
}
}
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);//剪枝需要的前提
func(0, candidates, new ArrayList<>(), target);
return res;
}
}