【代码随想录】算法训练营day24 | 回溯理论基础 + LeetCode77组合

文章介绍了回溯算法的基本概念,将其与递归关联,并指出其本质是穷举。通过代码模板展示了回溯函数的构造,强调了终止条件的重要性。以LeetCode的组合问题为例,解释了如何使用回溯算法解决多层遍历的难题,以及在实现过程中如何进行剪枝优化。
摘要由CSDN通过智能技术生成

回溯算法理论基础

代码随想录: 回溯算法理论基础

初印象

  1. 回溯是递归的副产品,只要有递归就会有回溯。
  2. 回溯的本质是穷举。
  3. 所有回溯法的问题都可以抽象为树形结构(N叉树)。
  4. 递归三要素:确定递归函数的参数和返回值、确定终止条件、确定单层递归的逻辑。
  5. 回溯三部曲:回溯函数模板返回值以及参数、回溯函数终止条件、回溯搜索的遍历过程。
void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}
  1. 回溯,撤销处理结果在代码中如何体现?

看视频讲解后的想法

  1. 组合、切割、子集、排列、棋盘等问题
  2. 终止条件语句后,存放完结果不要忘记return,之后用for循环进入单层搜索逻辑,处理节点。虽然代码中是先收集结果再处理节点,但在逻辑中是相反的顺序。
  3. 回溯撤销处理结果是指:比如在求1、2、3、4的组合问题中,求得1 2组合的结果的情况下,回溯弹出2压入3才能得到1 3组合。

LeetCode77组合

代码随想录: 组合问题
力扣: 77

初印象

  1. 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
    你可以按任何顺序返回答案。1 <= n <= 20。1 <= k <= n。

  2. 回溯三要素:参数与返回值,终止条件、遍历过程。参数是两个整数n和k。返回值两个数的组合。终止条件即叶子节点是组合中元素个数已达到k?那么程序终止条件呢?遍历过程可能借助栈。

  3. 为什么要用回溯算法? for循环,k=2时两层,k=3时三层……n=k=20时非常繁琐无法解决,需要借助回溯法。递归来做层叠嵌套(可以理解是开k层for循环),每一次的递归中嵌套一个for循环。 for循环控制树的横向遍历,递归控制树的纵向遍历。

  4. 抽象为二叉树,n是树的宽度,k是树的深度。

  5. 从左往右取,用startindex记录集合从何处开始遍历,防止出现重复的组合。

看视频讲解后的想法

  1. 程序终止条件通过for循环控制。回溯的终止条件是指比如1234中取2个数的组合,已经取得1得情况下,剩余234,未达到k=2,继续向下递归,取得2形成12组合,此时虽然还剩余34元素未利用,但是已经达到了终止条件k=2,所以终止,向上回溯。
  2. 由组合的定义可知,1234在首先取得2的情况下,剩下的元素既不能选1也不能选2,只能从34中选,所以需要一个int来记录遍历开始位置。
  3. for循环中需要一个i=startindex,传入i来递归回溯
  4. 剪枝
    树状结构图

实现过程中遇到的问题

一、原始版本

class Solution {
private:
    vector<vector<int>> result;//二维数组存放符合条件的结果的集合
    vector<int> path;//存放符合条件结果
    void backtracking(int n, int k, int startIndex) {
        if (path.size() == k) {//size后面加括号
            result.push_back(path);
            return;
        }
        for (int i = startIndex; i <= n; i++) {
            path.push_back(i);
            backtracking(n, k, i + 1);//这里是i+1
            path.pop_back();
        }
    }
public:
    vector<vector<int>> combine(int n, int k) {
        result.clear();
        path.clear();
        backtracking(n, k, 1);
        return result;
    }
};
  1. line 3:#include <vector
  2. line 4: using namespace std
  3. line10-13,回溯算法嵌套for循环的关键,for循环在树状图中横向,递归回溯在树状图中纵向。
  4. line13,传入的startIndex是i+1
  5. line23不要忘记分号

二、剪枝(未更新)

总结

对回溯算法有了一个初步的认识,重点是回溯三要素和回溯算法的模板。终止条件很重要,写不好就死循环。回溯算法能够抽象成n叉树的观点、回溯算法和for循环互相嵌套的观点很新颖,代码有不断复习的必要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值