题目链接:https://leetcode-cn.com/problems/combinations/
题目描述
思路
1 回溯
回溯法 是一种通过遍历所有可能成员来寻找全部可行解的算法。若候选 不是 可行解 (或者至少不是 最后一个 解),回溯法会在前一步进行一些修改以舍弃该候选,换而言之, 回溯 并再次尝试。
这是一个回溯法函数,它将第一个添加到组合中的数和现有的组合作为参数。 combineCore(start, curr)
- 若组合完成- 添加到输出中。
- 遍历从 start 到 n的所有整数。
- ( a ) 将整数 i 添加到现有组合 curr中。
- ( b ) 继续向组合中添加更多整数 : combineCore(start + 1, curr).
- ( c ) 将 i 从 curr中移除,实现回溯。
复杂度分析
- 时间复杂度:
O
(
k
C
N
k
)
O\left(k C_{N}^{k}\right)
O(kCNk) ,其中
C
N
k
=
N
!
(
N
−
k
)
!
k
!
C_{N}^{k}=\frac{N !}{(N-k) ! k !}
CNk=(N−k)!k!N!是要构成的组合数。push_back/pop_back操作是常数时间。唯一耗费时间的是将长度为
k
的组合添加到输出中。 - 空间复杂度: O ( C N k ) O\left(C_{N}^{k}\right) O(CNk),用于保存全部组合数以输出。
代码
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ret;
if(n<1 || k<1) return ret;
vector<int> curr;
combineCore(1, n, k,curr,ret);
return ret;
}
// 回溯
void combineCore(int start, int n, int k, vector<int> &curr, vector<vector<int>> &ret){
if(curr.size() == k) // 当前长度达到k
ret.push_back(curr);
for (int i = start; i < n+1; ++i) {
curr.push_back(i); // 选取i位置元素
combineCore(i+1, n,k, curr, ret);
curr.pop_back(); // 恢复
}
}
};