打卡Day24

本文详细介绍了回溯算法的基本概念,如其本质是暴力查找和递归结构,以及它在解决组合、切割、子集、排列和棋盘问题中的应用。提供了组合问题的实例代码,并强调了回溯算法的关键步骤:确定参数、设置终止条件和单层递归逻辑。
摘要由CSDN通过智能技术生成

回溯算法理论基础

什么是回溯算法:

本质为暴力查找,隐藏在递归的下面,就是一个“撤销处理结果”的过程

解决的问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合,强调元素不强调顺序
  • 切割问题:一个字符串按一定规则(例:回文)有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式,强调顺序
  • 棋盘问题:N皇后,解数独等等

如何理解回溯算法:

回溯算法本质都是找子集问题,因此可以抽象成一棵N叉树,集合的大小为树的宽度,递归的层数为树的深度。

回溯搜索的遍历过程:

回溯算法的模板:

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

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

77.组合

题目内容:给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

代码

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    vector<vector<int>> combine(int n, int k) {
        backtracking(n, k, 1);
        return result;
    }
    void backtracking(int n, int k, int start) {
        if(path.size() == k) {
            result.push_back(path);
            return;
        }
        for(int i = start; i <= n; i++) {
            path.push_back(i);
            backtracking(n, k, i+1);
            path.pop_back();
        }
        
    }
};

反思回溯算法三部曲:确定回溯算法参数(比递归的参数要难确定一些,可以边写变确定)、确定终止条件(收集结果)、确定单层递归的逻辑(注意还要把收集到的结果挤出去);

题目要求收集所有长度为k的组合,那么终止条件就是中间结果长度达到了k;

在收集的过程中,1 2、1 3、1 4、2 3等组合,如何使得收集到一个结果后,下一个组合从下一个数开始呢?那就是使用start,每次递归的时候start加1,就能从下一个数开始收集;

中间结果path收集到一个数之后记得把收集到的数再弹出,这样才能一直更新而不会累加。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值