39组合总和
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class day25_39_组合总和 {
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new LinkedList<>();
public static void main(String[] args) {
}
public List<List<Integer>> combinationSum(int[] candidates, int target) {
huisu(candidates, target, candidates.length);
return res;
}
void huisu(int[] cand,int target,int n){
//这一题每一个数可以无限次的 用
//所以终止条件就是sum等于所求
int sum=0;
for(int i=0;i<path.size();i++){
sum+=path.get(i);
}
if (sum==target) {
res.add(new ArrayList<>(path));
return;
}
for(int i=0;i<n;i++){
if (sum+cand[i]>target) {
break;
}
path.add(cand[i]);
//这里是把他加上
huisu(cand, target, n);
path.remove(path.size()-1);
}
}
}
这是自己写的第一版本代码,有一个错误,就是
这里的递归的循环初试不应该还是从0 开始,这样就会出现重复的值
应该从i接着开始,也就是可以重复用当前值,但是不会用前面的也就是不会重复
这才是正确的
还有一个点就是要先排序,这个是必要的,不然可能会漏掉答案
组合总和2
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class day25_40_组合总和二 {
public static void main(String[] args) {
}
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new LinkedList<>();
boolean[] demo;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
demo=new boolean[candidates.length];
huisu(candidates, target, candidates.length,0);
return res;
}
void huisu(int[] cand,int target,int n,int index){
//这一题每一个数可以无限次的 用
//所以终止条件就是sum等于所求
int sum=0;
for(int i=0;i<path.size();i++){
sum+=path.get(i);
}
if (sum==target) {
res.add(new ArrayList<>(path));
return;
}
for(int i=index;i<n;i++){
if (sum+cand[i]>target) {
break;
}
if(i>0&&cand[i]==cand[i-1]&&demo[i-1]==false){
continue;
}
path.add(cand[i]);
//这里是把他加上
demo[i]=true;
huisu(cand, target, n,i+1);
path.remove(path.size()-1);
demo[i]=false;
}
}
}
这个和上一题主要是两个不同,一个就是index要是i+1不能是i还有一个就是要去重,这里借用了一个数组进行状态标记非常巧妙,可以有效防止同一层前后元素重复,但是不影响下一层使用相同的元素,非常巧妙