Given two integers n and k, return all possible combinations of k numbers out of 1 … n.
- Example:
Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
解法一——深度优先搜索
求排列组合第一个想到的就是用深度优先搜索写出所有可能的组合
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
combinecore(n,k,1,res,new ArrayList<Integer>());
return res;
}
private void combinecore(int n, int k, int level, List<List<Integer>> res, ArrayList<Integer> out) {
// TODO Auto-generated method stub
if(out.size()==k)
{
res.add(new ArrayList<Integer>(out));
return;
}
for(int i=level;i<=n;i++)
{
//如果n-i<k-(out.size()+1),则提前退出。比如,i=4,4后面没有数字可选了,
//即n-i=0,而此时out.size()还为0,即使加入4这个数字,也只是1,即k-(out.size()+1)=1,
//那么它还需要一个数字,而实际上已经没有数字可选了,所以可以提前退出
//加上这个剪枝操作后,程序运行时间由27ms提升到了1ms
if(out.size()+n-i+1<k)
return;
out.add(i);
combinecore(n, k, i+1, res, out);
out.remove(out.size()-1);
}
}
Runtime: 1 ms, faster than 100.00% of Java online submissions for Combinations.
Memory Usage: 37.8 MB, less than 100.00% of Java online submissions for Combinations.
解法二
这种解法利用了排列组合的性质,即从四个里面选三个的组合可以分为选4和不选4,如果选4,那么从3个里面选一个然后再加上4;如果不选4,则从3个里面选2个,即C(4,3)=C(3,2)+C(3,1),扩展到n和k的话,这个公式可以写成:
C(n,k)=C(n-1,k-1)+C(n-1,k)
public List<List<Integer>> combine(int n, int k) {
if(k>n||k<0)
return new ArrayList<List<Integer>>();
if(k==0)
{
List<Integer> out=new ArrayList<Integer>();
List<List<Integer>> res=new ArrayList<List<Integer>>();
res.add(out);
return res;
}
List<List<Integer>> res=combine(n-1, k-1);
for(List<Integer> a:res)
a.add(n);
for(List<Integer> a:combine(n-1, k))
res.add(a);
return res;
}
Runtime: 3 ms, faster than 92.58% of Java online submissions for Combinations.
Memory Usage: 38 MB, less than 100.00% of Java online submissions for Combinations.