这道题目可以用动态规划的思想解决:
1~n中k个数的所有组合一定是由两部分组成:
第一部分,求(1~n-1)中k-1个数的所有组合,然后每个组合中加入元素n;
第二部分,求(1~n-1)中k个数的所有组合;
上述两部分合并便可以得到1~n中k个数的所有组合。
算法设计需要注意几个问题,避免不必要的bug:
判断 n<=0 时,组合为空
判断 n< k 时 (也就包括了 k<=0 的情况),组合均为空
判断 k==1 时, 1−n 每个元素为一个组合,返回 n 个组合
判断 n==k 时,此时只有一个组合,包括元素 1−n
vector<vector<int>> combine(int n, int k) {
if (n <= 0 || n < k)
return vector<vector<int>>();
//保存结果
vector<vector<int>> ret;
if (k == 1)
{
for (int i = 1; i <= n; i++)
{
vector<int> v(1,i);
ret.push_back(v);
}//for
return ret;
}//if
if (n == k)
{
vector<int> v;
for (int i = 1; i <= n; i++)
{
v.push_back(i);
}//for
ret.push_back(v);
return ret;
}//if
else{
//由两部分组成,第一部分为 1~n-1 中k-1个数的组合,每个组合加入元素n
vector<vector<int>> tmp = combine(n - 1, k - 1);
int len = tmp.size();
for (int i = 0; i < len; i++)
{
tmp[i].push_back(n);
ret.push_back(tmp[i]);
}//for
//第二部分,1~n-1中 k个数的组合,两部分合并得到最终结果
tmp = combine(n - 1, k);
len = tmp.size();
for (int i = 0; i < len; i++)
{
ret.push_back(tmp[i]);
}//for
return ret;
}//else
}
还可以用深度优先遍历DFS去解决:
vector<vector<int>> combine(int n, int k) {
vector<vector<int> > result;
vector<int> path;
dfs(n,k,result,path,1,0);
return result;
}
void dfs(int n,int k,vector<vector<int> > &result,vector<int> &path,int start,int step)
{
if(step==k)
{
result.push_back(path);
return;
}
for(int i=start;i<=n-k+1+step;++i)
{
path.push_back(i);
dfs(n,k,result,path,i+1,step+1);
path.pop_back();
}
}