问题:
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
For example,
If n = 4 and k = 2, a solution is:
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
① 使用dfs列出所有的可能。
class Solution {//26ms
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
dfs(n,k,1,list,res);
return res;
}
public void dfs(int n,int k,int i,List<Integer> list,List<List<Integer>> res){
if(list.size() == k){
res.add(new ArrayList<Integer>(list));
}
for (int j = i;j <= n ;j ++ ) {
list.add(j);
dfs(n,k,j + 1,list,res);
list.remove(list.size() - 1);
}
}
}
② 每次匹配之后,待匹配的个数k都会减少。进化版。
根据两个规则:
1) 组合中第1位的有效范围是[1,n-k+1]。
2) 组合中第i位的有效范围是[i + 1,n-k+1+i]。
class Solution {//4ms
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
dfs(n,k,1,list,res);
return res;
}
public void dfs(int n,int k,int i,List<Integer> list,List<List<Integer>> res){
if(k == 0){//待匹配的个数
res.add(new ArrayList<Integer>(list));
return;
}
for(int j = i;j <= n + 1 - k;j ++){
list.add(j);
dfs(n,k - 1,j + 1,list,res);
list.remove(list.size()-1);
}
}
}
③ 在discuss中看到了这个方法,由大到小添加值。
class Solution {//5ms
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
dfs(n,k,list,res);
return res;
}
private void dfs(int n, int k,List<Integer> list,List<List<Integer>> res) {
if (n < k) {
return;
}
if (k == 0) {
res.add(new ArrayList<>(list));
return;
}
list.add(n);
dfs(n - 1,k - 1,list,res);
list.remove(list.size() - 1);
dfs(n - 1,k,list,res);
}
}