求全组合
例如,在[1,n]这n个数中,选择k个数,那么总共有多少种可能?把这些可能都列出来?
我们在数学上,
C
n
k
C_n^k
Cnk种可能一一列举出来。
计算机在解决这个问题时,我们采用的时DFS的思路
思路一:全排列剪枝
组合问题实际是排列问题在不考虑数字顺序的情况
在[1,n]这n个数中,选择k个数,那么我们首先选择第一个数,然后选择第二个数,然后选择第三个数,直到选择到第k个数。
既然组合问题它不考虑数字的顺序,那么我们不妨永远保持它从小到大,即在选择数的时候,要求这个数要比已经选择的所有数大。
vector<int> temp;
vector<vector<int>> results;
void dfs(int n,int k,int level)
{
//level表示目前在取第几个数
if(level==k+1)
{
results.push_back(temp);
return;
}
int i=1;
if(temp.size()!=0)
{
i=temp[temp.size()-1]+1;//即temp种最大的数+1
}
while(i<=n)
{
temp.push_back(i);
dfs(n,k,level+1);
temp.pop_back();
i++;
}
}
思路二:
我们同样采用DFS算法,但是我们的思路是,依次考察1,2,…,k这些数,分别考虑它们在不在结果中,这种算法更加优越,因为它无形中就暗含着结果中数字是从小到大排序的。
vector<int> temp;
vector<vector<int>> results;
void dfs(int n,int k,int cur)
{
//我们的思路是考察cur这个数是不是在temp中,一种是在,一种是不在
//考察cur这个数时,[1,cur-1]都已经考察完了
if(temp.size()==k)
{
results.push_back(temp);
return;
}
//如果temp中的数的个数加上剩下没考虑的数 的个数之和小于k,这种就没必要选取了
if(n-cur+1+temp.size()<k)
{
return;
}
//cur在temp中
temp.push_back(cur);
dfs(n,k,cur+1);
temp.pop_back();
//cur不在temp中
dfs(n,k,cur+1);
}