Leetcode216 找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
所有数字都是正整数。
解集不能包含重复的组合。
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
整体的思路与求Leetcode77组合问题一样,相当于又多了一个全局变量sum。
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
int sum=0;
public List<List<Integer>> combinationSum3(int k, int n) {
if(k>9) return result;
backTracking(n,k,1);
return result;
}
public void backTracking(int n,int k,int startIndex){
if(path.size()+(9-startIndex)+1<k) return;
if(sum>n) return;
if(path.size()==k){
if(sum==n){
result.add(new ArrayList<>(path));
}
return;
}
for(int i=startIndex;i<=9;i++){
path.add(i);
sum+=i;
backTracking(n,k,i+1);
sum-=i;
path.remove(path.size()-1);
}
}
Leetcode39
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制重复被选取。
List<List<Integer>> result = new ArrayList<>();
List<Integer> list = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
//Arrays.sort(candidates);
int sum=0;
backTracking(candidates,target,sum,0);
return result;
}
public void backTracking(int[] candidates,int target ,int sum,int startIndex){
if(sum>target) return;
if(sum==target){
result.add(new ArrayList(list));
return;
}
//for(int i=startIndex;i<candidates.length&&(sum+candidates[i])<target)
for(int i=startIndex;i<candidates.length;i++){
list.add(candidates[i]);
sum+=candidates[i];
backTracking(candidates,target,sum,i);
sum-=candidates[i];
list.remove(list.size()-1);
}
}
//基于数组可排序
//判断sum>target本身其实是递归一次之后才能判断
//优化的代码见注释
Leetcode40
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
//相比较leetcode39,多了得到的组合不能重复这一限制。
List<List<Integer>> result = new ArrayList<>();
List<Integer> list = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backTracking(candidates,target,0,0);
return result;
}
//1,1,2,5,6,7,10
public void backTracking(int[] candidates,int target,int startIndex,int sum){
if(sum>target) return;
if(sum==target){
result.add(new ArrayList(list));
return;
}
for(int i=startIndex;i<candidates.length&&(sum+candidates[i])<=target;i++){
list.add(candidates[i]);
sum+=candidates[i];
backTracking(candidates,target,i+1,sum);
sum-=candidates[i];
list.remove(list.size()-1);
//解决出现两次[1,2,5]的情况
/*
可以理解为:第一轮for循环得到的结果集合开头全为1,那么第二轮开始,
集合开头还为1就可以去掉(同一层去重),在每一层递归中都是适用的。
*/
while(i<candidates.length-1&&candidates[i]==candidates[i+1]){
i++;
}
}
}