77. 组合
组合问题。不需要used[]数组,限定下一次循环/搜索的起点即可.
本题不含重复数字且每个数字不可重复选择.
本题有另一种思路,即对每个数字有选与不选两种选择。
还有提前终止,时间优化很明显:
事实上,如果 n = 7, k = 4,从 55 开始搜索就已经没有意义了,这是因为:即使把 55 选上,后面的数只有 66 和 77,一共就 33 个候选数,凑不出 44 个数的组合。因此,搜索起点有上界,这个上界是多少,可以举几个例子分析。
class Solution {
LinkedList<List<Integer>> ans=new LinkedList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(1,0,n,k);
return ans;
}
void dfs(int begin,int cnt,int n,int k){//k是退出递归的关键,cnt是当前数目,n是循环边界
if(cnt==k){
ans.add(new LinkedList(path));
return;
}
for(int i=begin;i<=n;i++){
path.add(i);
dfs(i+1,cnt+1,n,k);//看递归退出条件,是已经收集好了以i为起点的数据/i不是第一个,但是是个起点--不要写begin+1
path.removeLast();//找下一个起点,先把当前的删去
}
}
}
每个数字有选与不选两种选择:(时间和上一版本差不多)
class Solution {
LinkedList<List<Integer>> ans=new LinkedList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(1,n,k);
return ans;
}
void dfs(int cur,int n,int k){//k是退出递归的关键,cnt是当前数目,n是循环边界
if(k==0){
ans.add(new LinkedList(path));
return;
}
//递归终止,避免越界
if(cur==n+1)return;
dfs(cur+1,n,k);//不选当前数字
path.add(cur);//选当前数字
dfs(cur+1,n,k-1);
path.removeLast();
}
}
以下是升级版递归终止条件,只需要改一个判断即可,见代码
class Solution {
LinkedList<List<Integer>> ans=new LinkedList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(1,n,k);
return ans;
}
void dfs(int cur,int n,int k){//k是退出递归的关键,cnt是当前数目,n是循环边界
if(k==0){
ans.add(new LinkedList(path));
return;
}
//这里要及时判断,避免越界
//if(cur==n+1)return;
//以下是升级版递归终止条件
if(cur>n-k+1)return;
dfs(cur+1,n,k);//不选当前数字
path.add(cur);//选当前数字
dfs(cur+1,n,k-1);
path.removeLast();
}
}

浙公网安备 33010602011771号