递归型(回溯法)
class Solution {
public:
vector<vector<int>> ans;
int n;
int k;
void dfs(int pre,vector<int> v)
{
if(v.size()==k)
{
ans.push_back(v);
return;
}
if(pre>n)return;
for(int i=pre+1;i<=n;i++)
{
v.push_back(i);
dfs(i,v);
v.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
this->n=n;
this->k=k;
dfs(0,{});
return ans;
}
};
- 时间复杂度:
O(C(n,k)*k) - 空间复杂度:
O(n+k),即递归使用栈空间的空间代价和临时数组v的空间代价。
非递归型(字典序法)
class Solution {
public:
string& nextone(string& s)
{
// 长度为n的s,其中包含k个'1'与n-k个'0'
// 按照字典序,求当前s的下一个s
// 例如
// 00111 -> 01011 -> 01101 -> 01110 -> 10011
// -> 10101 -> 10110 -> 11001 -> 11010 -> 11100
// 取最右边但不是末尾的0
// 右边的1与紧邻左边的0作swap
// 如果这个0不是最右边的0
// 被swap的1后面的1都移至最右边
int rht = s.size() - 1;
bool isend = true;
while (rht >= 0 && s[rht] == '0')
{
isend = false;
rht--;
}
if (rht < 0)
{
// 00000
s = "";
return s;
}
int lft = rht;
while (lft >= 0 && s[lft] == '1')
{
lft--;
}
if (lft < 0)
{
// 11100, the last one
s = "";
return s;
}
if (lft >= 0 && s[lft] == '0')
{
swap(s[lft], s[lft + 1]);
}
if (!isend)
{
rht = s.size() - 1;
lft = lft + 2;
while (lft < rht && s[lft] == '1' && s[rht] == '0')
{
s[lft++] = '0';
s[rht--] = '1';
}
}
return s;
}
vector<vector<int>> combine(int n, int k) {
string s = string(n-k, '0') + string(k, '1');
vector<vector<int>> ans;
while (s != "")
{
vector<int> v;
int i = 0;
while (i++ < n)
{
if (s[n-i] == '1')v.push_back(i);
}
ans.push_back(v);
nextone(s);
}
return ans;
}
};
- 时间复杂度:
O(C(n,k)*k),要求C(n,k)次nextone,每次nextone对k个'1'的位置进行调整,循环操作从k到n次 - 空间复杂度:
O(k),即临时数组v的空间代价。
int main()
{
Solution sol;
int n = 5, k = 3;
string s = string(n-k, '0') + string(k, '1');
int t = 0;
while (s != "")
{
cout << ++t << ": \t" << s << endl;
sol.nextone(s);
}
cout << "---" << t << "---" << endl;
vector<vector<int>> ans = sol.combine(n, k);
t=0;
for (auto v : ans)
{
cout << ++t << ": \t";
for (auto a : v)cout << a << " ";
cout << endl;
}
}
输出
1: 00111
2: 01011
3: 01101
4: 01110
5: 10011
6: 10101
7: 10110
8: 11001
9: 11010
10: 11100
---10---
1: 1 2 3
2: 1 2 4
3: 1 3 4
4: 2 3 4
5: 1 2 5
6: 1 3 5
7: 2 3 5
8: 1 4 5
9: 2 4 5
10: 3 4 5