原题地址(中等)

这个题就是很经典的回溯题。
我发现这类题有个共同的特点,(也可以说是回溯的特点吧),就是回溯函数中,一般都是如下结构:

  • 减枝条件+终止条件;
  • 递归条件:情况1:考虑当前元素; 情况2:不考虑当前元素


也就是官方题解中说的[
递归实现组合型枚举](https://leetcode-cn.com/problems/combinations/solution/zu-he-by-leetcode-solution/)

模板如下:

  1. vector<int> temp;
  2. void dfs(int cur, int n) {
  3. if (cur == n + 1) {
  4. // ...
  5. return;
  6. }
  7. // 考虑选择当前位置
  8. temp.push_back(cur);
  9. dfs(cur + 1, n, k);
  10. temp.pop_back();
  11. // 考虑不选择当前位置
  12. dfs(cur + 1, n, k);
  13. }



代码里第一个减枝非常精髓,耗时可以提高非常多。

  1. class Solution {
  2. public:
  3. vector<int> v;
  4. vector<vector<int>> ans;
  5. void dfs(int cur, int k, int n){
  6. // 剪枝:temp 长度加上区间 [cur, n] 的长度小于 k,不可能构造出长度为 k 的 temp
  7. if (v.size() + (n - cur + 1) < k)
  8. return;
  9. if(v.size() == k){
  10. ans.push_back(v);
  11. return;
  12. }
  13. v.push_back(cur);
  14. dfs(cur+1, k, n);
  15. v.pop_back();
  16. dfs(cur+1, k, n);
  17. }
  18. vector<vector<int>> combine(int n, int k) {
  19. dfs(1, k, n);
  20. return ans;
  21. }
  22. };