描述
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
分析
“组合总和” 系列题解汇总:
39. 组合总和
40. 组合总和 II
216. 组合总和 III
377. 组合总和 Ⅳ
本题是组合问题,相同元素不同排列仍然看作一个结果。
穷经所有的可能子集,若和等于target,加入最终结果集合。
给nums排序是为了方便剪枝,提前结束不必要的递归。
import java.util.*;
public class Solution {
ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
public ArrayList<ArrayList<Integer>> combinationCount (int target, int[] nums) {
Arrays.sort(nums);
backTrace(new ArrayList<>(),nums,0,target);
return ans;
}
public void backTrace(ArrayList<Integer> list, int[] nums, int index, int target){
if(target == 0){
ans.add(new ArrayList<>(list));
return ;
}
if(target < 0){
return ;
}
for(int i = index; i < nums.length && nums[i] <= target; i++){
list.add(nums[i]);
backTrace(list, nums, i, target-nums[i]);
list.remove(list.size()-1);
}
}
}
import java.util.Arrays;
import java.util.ArrayList;
class Solution {
/*
回溯思想
candidates排序,从左到右,各个数独自添加进list,同时更新target,target=target-candidates[i].
重复此过程直到target==0或者小于0,当target==0,即正确结果添加进最终集合res.
[2,3,6,7],target=7
把2添加进list,更新target=7-2=5。递归此过程,看作是[2,3,6,7],target=5.直到target=0或者小于0结束.
同理考虑3,6,7
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
if(candidates == null || candidates.length == 0){
return res;
}
Arrays.sort(candidates);
process(candidates,0,target,new ArrayList<>(),res);
return res;
}
public void process(int[] candidates, int start, int target, List<Integer> list, List<List<Integer>> res){
if(target == 0){
res.add(new ArrayList<>(list));
return;
}
int i = start;//start是上一次选择的数
//tmp集合只属于本次递归,上一层递归,下一层递归都有它自己的集合,只是继承下来但互不影响。
List<Integer> tmp = new ArrayList<>(list);
//i < candidates.length要在candidates[i]前面,否则会报数组越界
while(i < candidates.length && target >= candidates[i]){
tmp.add(candidates[i]);
process(candidates,i,target-candidates[i],tmp,res);
tmp.remove(tmp.size()-1);//删除加入的数,恢复加入数之前的状态
i++;
}
return;
}
}