题目描述
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
示例:
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combinations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
就一般dfs,然后选k个数结束递归,本着提升总提交正确率的心态 ,光速写了一个dfs过了
class Solution {
public:
vector<vector<int>> ans;
void dfs(int x, int k, vector<int>& vec, int start, int n)
{
if(x==k) {ans.push_back(vec); return;}
for(int i=start; i<=n; i++)
{
vec.push_back(i);
dfs(x+1, k, vec, i+1, n);
vec.pop_back();
}
}
vector<vector<int>> combine(int n, int k)
{
vector<int> vec;
dfs(0, k, vec, 1, n);
return ans;
}
};
翻了评论区发现有一个老哥的方法相当骚,思路如下:
我们总是要在n个数中选取k个数,可以用 0,1 标识 不选,选 两种情况
- 对于n个数,我们设置一个长度为n的数组select[i],
select[i]==1
表示第i
个数需要被选(第0个数是1) - 总是要选k个,一开始时令
select[0]~select[k-1]
全部置 1,表示初始的状态 - 通过prev_permutation函数生成降序全排列,每一种全排列代表着一个答案
代码
class Solution {
public:
vector<vector<int>> combine(int n, int k)
{
vector<vector<int>> ans;
vector<int> select(n);
for(int i=0; i<k; i++) select[i]=1;
do
{
vector<int> Ans;
for(int i=0; i<n; i++)
if(select[i]) Ans.push_back(i+1);
ans.push_back(Ans);
}while(prev_permutation(select.begin(), select.end()));
return ans;
}
};
可以看到两者速度差距明显,库函数全排列还是非常快的如果用一个int或者long做状态压缩,会更快