题目链接:点击这里
递归:
class Solution {
public:
void dfs(int start, int n, int k, vector<int>& tmp, vector<vector<int>>& ans)
{
if(tmp.size()==k)
{
ans.push_back(tmp);
return;
}
for(int i = start; i <= n; i++)
{
tmp.push_back(i);
dfs(i+1, n, k, tmp, ans);
tmp.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ans;
vector<int> tmp;
dfs(1, n, k, tmp, ans);
return ans;
}
};
美版的题解,神来之笔:
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ans;
vector<int> b(k,0);
int i = 0;
while(i>=0)
{
b[i]++;
if(b[i]>n)
i--;
else if(i==k-1)
ans.push_back(b);
else
{
i++;
b[i] = b[i - 1];
}
}
return ans;
}
};
二进制位的角度:
预备知识:利用二进制位生成子集:点击这里
由上可知,一个子集对应一个二进制数,一个有 个元素的子集,它对应的二进制数中有 个 。
那么,问题就转化为查找 的个数为 的二进制数,这些二进制数就是我们想要的结果。
位运算可快速判断二进制数中 的个数为 :
kk = kk&(kk-1)
即清除 中的最后一个1。连续进行这个操作可统计出 的个数。- 树状数组中
lowbit(x) = x & -x
功能是计算 的二进制数的最后一个
在子集生成的代码基础上AC本题:
class Solution {
public:
void print_subset(int n, int k, vector<vector<int>>& ans)
{
for(int i = 0; i < (1<<n); i++)
{
int num = 0, kk = i; //num统计i中1的个数
while(kk)
{
kk = kk&(kk-1); //清除kk中的最后一个1
num++; //统计1的个数
}
if(num==k) //二进制数中的1有k个,符合条件
{
vector<int> tmp;
for(int j = 0; j < n; j++)
if(i&(1<<j)) //判断i的第j位是否为1
tmp.push_back(j+1);
ans.push_back(tmp);
}
}
}
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ans; //保存最后结果
print_subset(n, k, ans);
return ans;
}
};