39. 组合总和 【中等题】【回溯】
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
输入: 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]
]
【历史重难点题目】
【思路】
help(candidates,start+1,end,target,list,ans)
表示不取help(candidates,start,end,target-candidates[start],list,ans)
表示取【代码】
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans=new ArrayList<>();
help(candidates,0,candidates.length,target,new ArrayList<>(),ans);
return ans;
}
void help(int[] candidates, int start, int end,int target,List<Integer> list,List<List<Integer>> ans){
if(target==0){
ans.add(new ArrayList<>(list));
return;
}
if(start>=end || target<0)
return;
help(candidates,start+1,end,target,list,ans);
list.add(candidates[start]);
help(candidates,start,end,target-candidates[start],list,ans);
list.remove(list.size()-1);
}
【备注】
target-candidates[start]>=0
的判断条件,做一定的剪枝public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans=new ArrayList<>();
help(candidates,0,candidates.length,target,new ArrayList<>(),ans);
return ans;
}
void help(int[] candidates, int start, int end,int target,List<Integer> list,List<List<Integer>> ans){
if(target==0){
ans.add(new ArrayList<>(list));
return;
}
if(start>=end || target<0)
return;
help(candidates,start+1,end,target,list,ans);
if(target-candidates[start]>=0){
list.add(candidates[start]);
help(candidates,start,end,target-candidates[start],list,ans);
list.remove(list.size()-1);
}
}
ans.add(new ArrayList<>(list))
对于这一行代码有些读者可能有疑问,为什么不能直接ans.add(list)
呢?这是一个传值和传引用的问题【点此详见解析】【代码】
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans = new ArrayList<>();
if(candidates==null) return ans;
help(ans,new ArrayList<>(),0,target,candidates);
return ans;
}
void help(List<List<Integer>> ans,List<Integer> cur,int start,int target,int[] candidates){
if(target==0){
ans.add(new ArrayList(cur));
return;
}else{
for(int i=start ; i<candidates.length ; i++){
if(target-candidates[i]>=0){
cur.add(candidates[i]);
help(ans,cur,i,target-candidates[i],candidates);
cur.remove(cur.size()-1);
}
}
}
}
【备注】
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> ans = new ArrayList<>();
if(candidates==null) return ans;
help(ans,new ArrayList<>(),0,target,candidates);
return ans;
}
void help(List<List<Integer>> ans,List<Integer> cur,int start,int target,int[] candidates){
if(target==0){
ans.add(new ArrayList(cur));
return;
}
if(target<0)
return;
for(int i=start ; i<candidates.length ; i++){
if(target-candidates[i]>=0){
cur.add(candidates[i]);
help(ans,cur,i,target-candidates[i],candidates);
cur.remove(cur.size()-1);
}
else
break;
}
}
关注微信公众号“算法岗从零到无穷”,更多算法知识点告诉你。