77. 组合【 力扣(LeetCode) 】
文章目录
- 零、原题链接
- 一、题目描述
- 二、测试用例
- 三、解题思路
- 四、参考代码
零、原题链接
77. 组合
一、题目描述
给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
你可以按 任何顺序 返回答案。
二、测试用例
示例 1:
输入:n = 4, k = 2
输出:
[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],
]
示例 2:
输入:n = 1, k = 1
输出:[[1]]
提示:
1 <= n <= 20
1 <= k <= n
三、解题思路
- 基本思路:
回溯法 + 剪枝。
为了保证不重复,我们只需要保证每个序列都是递增,所以序列的每个位置取值都有范围,第 i 个数的取值范围为[i,n-k+i]
- 具体思路:
- 回溯:
- 如果该元素超出该位置的范围,则返回。【剪枝】
- 序列 vec 添加该元素。
- 如果是最后一个元素,则将序列 vec 添加到 ans 并弹出最后一个元素。
- 递归遍历下一个位置的元素。
- 弹出最后一个元素【回溯要恢复状态】
- 回溯:
四、参考代码
时间复杂度: O ( k ⋅ C n k ) \Omicron(k\cdot C_n^k) O(k⋅Cnk) 【一共 C n k C_n^k Cnk 的序列,每个序列 k 个元素】
空间复杂度: O ( k ) \Omicron(k) O(k) 【递归栈最深为 k 】
class Solution {
public:vector<vector<int>> ans;vector<int> vec;int _n;void dfs(const int& i, const int& k) {if (i > _n - k + 1)return;vec.emplace_back(i);if (k == 1) {ans.emplace_back(vec);vec.pop_back();return;}for (int j = i + 1; j <= _n; j++) {dfs(j, k - 1);}vec.pop_back();}vector<vector<int>> combine(int n, int k) {_n = n;int t = n - k + 1;for (int i = 1; i <= t; i++)dfs(i, k);return ans;}
};