Skip to content

代码随想录 回溯算法:77. 组合

题目分类

给定两个整数 nk,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

思考

直接的解法是嵌套for循环,外层选第一个数,内层再选第二个数。如果k=2,那么两层就可以解决。但是这里k不确定,我们怎么知道要写多少层?

回溯搜索可以解决这个问题,虽然也是暴力,但能写出来。

之前理解回溯法一棵树,横向是for循环,纵向是递归。这道题可以理解为k层for循环

回溯法三部曲
  • 回溯函数参数即返回值

    n K startIndex,这个 startIndex 控制是本层递归中,集合元素的可选范围,为什么需要?因为这道题是组合问题,如果每次递归都是从相同的集合选,会导致出现重复的组合。例如第一次选了1,第二次选了2,和第一次选2,第二次选1是一样的。而 startIndex 则会在第二套的第二次选择时为2,代表第二次选择只能从集合里面第二个元素以后选,这样第二次就不会再选{2,1}的情况

  • 终止条件

    path大小为k的时候,认为达到了叶子节点,将path加入到结果中,终止。

  • 回溯搜索的遍历过程

    for循环每次从startIndex 开始遍历,然后用path保存取出的节点i。

    这里使用了回溯的标准写法:

    先处理节点/做出选择,再进入递归函数,函数结束再撤销选择。

代码实现

C++
class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(int n,int k,int startIndex){
        if(path.size() == k) {
            result.push_back(path);
            return;
        }
        for(int i = startIndex;i <=n;i++){
            path.push_back(i);
            backtracking(n,k,i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        result.clear();
        path.clear();
        backtracking(n,k,1);
        return result;
    }
};