77. 组合

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]]

回溯法解题思路:

回溯法,一般可以解决如下几种问题:

组合问题:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等

另外,会有一些同学可能分不清什么是组合,什么是排列?

组合是不强调元素顺序的,排列是强调元素顺序。

例如:{1, 2} 和 {2, 1} 在组合上,就是一个集合,因为不强调顺序,而要是排列的话,{1, 2} 和 {2, 1} 就是两个集合了。

记住组合无序,排列有序,就可以了。

回溯法解决的问题都可以抽象为树形结构,是的,我指的是所有回溯法的问题都可以抽象为树形结构!

因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度,都构成的树的深度。

力扣77. 组合-LMLPHP

回溯算法模板框架如下:

//这份模板很重要,后面做回溯法的题目都靠它了!
void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>>res;
        vector<int>tem;
        backtracking(n,k,1,tem,res);
        return res;
    }
//回溯算法
    void backtracking(int n,int k,int startindex,vector<int>& tem,vector<vector<int>>& res)
    {
         //比如1,2已经满足条件则加入res,递归返回
        if (tem.size()==k)
        {
            res.push_back(tem);
            return;
        }
        else
        {
            for(int i=startindex;i<=n;i++)
            {
                tem.push_back(i);
                backtracking(n,k,i+1,tem,res);
                tem.pop_back();    //这步很关键
            }
        }
    }
};

以上内容参考自公众号:代码随想录

04-20 19:27