回溯算法第零篇【递归、搜索与回溯】【回溯算法入门必看】

2023-12-19

本篇文章的目的:

(1)给小伙伴们对回溯算法中的名词进行解释

(2)消除递归的恐惧(回溯是递归的一个分支)

给小伙伴们一个建议:整篇文章都要看完,一字不漏,全是干货。

注意: 分析回溯的思想之前,我们得知道一个关系——递归包含搜索,搜索包含回溯。所以我们在学习的顺序应该是先了解递归,再了解搜索,最后才是了解回溯算法是个啥,这样学起来既有趣也轻松!

各位小伙伴如果想进一步了解回溯算法,可以看我的回溯系列的文章,此系列会一直更新!!!

目录

1. 递归

1.1 什么是递归

1.2 为什么会用到递归

1.3 如何理解递归

1.4 如何写好一个递归

2. 搜索和遍历的名词解析

2.1 拓展搜索问题

3. 回溯和剪枝


1. 递归

1.1 什么是递归

  • 递归就是一个函数在它的函数体内调用它自身。 执行递归函数将反复调用其自身,每调用一次就进入新的一层。递归函数必须有结束条件。在求f(n)的时候,你就默认f(n -1)已经被求出来了,至于怎么求的,这个是计算机通过回溯求出来的,也就是涉及到栈的存储结构。
  • 递归函数有两个要素: (1)边界条件 确定递归到何时终止,也称为递归出口。 (2)递归模式: 大问题是如何分解为小问题的 ,也称为递归体。递归函数只有具备了这两个要素,才能在有限次计算后得出结果

递归函数的主要目的 就是 “大事化小,小事化了”。 递归和二叉树是密切相关的,可以尝试通过二叉树的数据结构来理解递归是如何将一个问题拆分成若干子问题,求解再回溯的,得到最终答案。

给大家举个几个例子,方便大家的理解:

第一个例子(二叉树的遍历):

如果大家对二叉树的先、中和后序遍历等二叉树功能的模拟实现有兴趣, 可以看下面这篇博客:

Java版数据结构——二叉树的模拟实现全代码-CSDN博客

第二个例子(快速排序):

如果大家对快速排序和归并排序还不是很了解, 可以看下面这两篇博客(超级详细):

深入浅出排序算法之快速排序(重要)⭐⭐⭐⭐⭐-CSDN博客

深入浅出排序算法之归并排序-CSDN博客

快速排序也是同一个意思:主问题和子问题都是,也就是上面提到的递归是起“大事化小,小事化了”的功能,主问题是大事,子问题是小事,主问题(大事)和子问题(小事)都具有相同的解决问题的步骤。

快排是 ① 先将第一个元素放到合适的位置,② 然后左右分,③ 再分别对左右进行快排;主问题和子问题都是这三个步骤。

说到这里,大家是不是都有点感觉啦!?如果还有些懵,请不要急,继续往下看!!!

1.2 为什么会用到递归

说到为什么会有递归,我们就要讨论递归的本质是什么?

在上面的二叉树和快排的例子中,我一直提到两个名字,主问题(大事)和子问题(小事)。主问题和子问题都具有相同的解题步骤。

主问题 -> 子问题;子问题 -> 子问题;子问题 -> 子问题 …… 直到把“小事化了”!!!

注意: 因为主问题和子问题们的解题步骤都是一样,所以他们可以用一个函数来统一解决。这就有了递归的出现啦。

1.3 如何理解递归

根据我的学习,觉得递归的理解可以分为如下三种层次:

第一层:从递归展开图的细节理解递归

  • 这种理解方式,适合入门,但不适合长期使用。 为什么呢?如果一道题十分简单(例如:用递归的方式打印数组),那么他的递归展开图可能就会比较简单(递归打印数组的递归展开图是一棵单分支的树);假设一道题的递归方法解题的递归展开图是一棵多分支树,那用这种方式学递归就十分痛苦了,可能一道中等的题目用递归解题的递归展开图三、四张A4纸都写不完!

注意: 上面提到的展开图是单分支树还是多分支树,大家如果不是很明白,不要紧的。下面会对递归展开图进一步解释。大家只需要知道递归展开图是多分支的话,画起来比单分支树更耗费纸张和时间。

第二层:从二叉树中的题目理解递归

  • 来到这一层,证明各位小伙伴们已经开始入门啦。二叉树的设计就是根据递归来设计的,二叉树的先、中和后序遍历都是可以用递归的方式来实现。二叉树的其他操作都是根据遍历实现,也就是说二叉树的其它操作也是可以用递归实现的。了解二叉树的模拟实现,可以使我们对递归的了解上升一个台阶。

注意: 这里有一篇博客,里面有Java版的二叉树模拟实现的所有代码。

Java版数据结构——二叉树的模拟实现全代码-CSDN博客

第三层:从宏观角度看待递归过程

能来到这一层,证明各位小伙伴对递归的理解已经很透彻了。在此我详细分享一下,如果宏观来理解递归:

  • 一: 不要在意递归的细节展开图
  • 二:把递归的 函数 当成一个 “黑盒”
  • 三:我们的无条件的相信 “黑盒” 可以为我们解决当前的子问题(再次强调,递归中的每个子问题的解题步骤都是一样)

1.4 如何写好一个递归

(1)先找到相同的子问题!!!

找到相同的子问题十分重要, 这一步关乎到函数头的设计 。例如:二叉树的先序遍历,首先我们知道遍历的方式是 根 -> 左 -> 右 ,目的是遍历,所以不需要返回值(void),需要有当前根结点传入(需要参数TreeNode root)。 故有函数头:public void prevOrder(TreeNode root)

(2)只关心某一个子问题是如何解决的

这一部分涉及函数体的书写,还是拿二叉树的先序遍历举例:遍历方式是根->左->右,所以函数体要把根->左->右给完成了!

(3)注意一下递归函数的出口

递归函数不能一直递归下去,一定要有终止条件。例如二叉树的遍历的终止条件就是 root == null。

具体的例题,在我的下一篇回溯算法文章中!

2. 搜索和遍历的名词解析

对比: 搜索 vs 深度优先遍历 vs 深度优先搜索 vs 宽度优先遍历 vs 宽度优先搜索 vs 暴搜

(1)深度优先遍历 vs 深度优先搜索 vs 宽度优先遍历 vs 宽度优先搜索

遍历和搜索区别不大 ,可以这么理解, 遍历是形式,目的是搜索 。用深度遍历(搜索)还是宽度遍历(搜索)主要看题目,他们也是在遍历(搜索)的顺序上有些区别而已。

深度优先搜索有个简称:dfs;宽度优先搜索有个简称:bfs

(2)搜索 vs 暴搜

搜索就是暴力地枚举一遍所有的情况。 搜索包含了暴搜,暴搜包含了深度优先搜索和宽度优先搜索

2.1 拓展搜索问题

用全排列举例

我们可以发现,用递归解决全排列的问题的递归展开图是一棵多叉树。还好这道题给的例子只有{1,2,3}三个元素,如果是10个呢?100个呢?这时候把所有情况按递归展开图画出来就不现实了。这就是我前面说的理解递归的第一层, 从递归展开图的细节理解递归

我们用第三层的思路来理解:

(1)确定相同的子问题:每一次选一个元素,不能选择已经选过的元素。不需要返回值(因为将最终结果存放到了全局变量中),参数需要数组 int[] nums。 故有函数头public void dfs(int[] nums)

(2)只关心一个子问题如何解决的。此题要记录哪个位置已选择,从哪个位置继续开始选,把当前选择的元素加入全局数组中。

(3)递归出口:数组的元素都被选过了,或者说来到了树的叶子结点处。

如果大家对这道题还不理解,不要紧,我在这里只是想让大家知道怎么用第三层的思路来思考递归问题。 全排列的细节问题并没有展开分享,详细内容在如下的博客中 (建议大家先把递归和深搜学明白再来回头看这篇文章):

回溯算法第二篇(全排列【基于排列树实现】、旅行售货员问题【基于排列树实现】、N皇后【基于子集树实现的】)-CSDN博客

3. 回溯和剪枝

回溯并不神秘,本质就是深搜!!!

这里用一个迷宫来分享我对回溯和剪枝的理解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

回溯算法第零篇【递归、搜索与回溯】【回溯算法入门必看】 的相关文章

随机推荐

  • 基于Spring Boot旅游景点订票系统设计与实现-计算机毕业设计源码68524

    摘 要 科技进步的飞速发展引起人们日常生活的巨大变化 电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用 信息时代的到来已成为不可阻挡的时尚潮流 人类发展的历史正进入一个新时代 在现实运用中 应用软件的工作规则和开发步
  • springboot+mysql宠物领养系统-计算机毕业设计源码46903

    目 录 摘要 1 绪论 1 1 意义 1 2
  • Manacher算法(马拉车)

    Manacher 马拉车 算法 作用 在On的时间复杂度下 求出字符串每个回文中心的最长回文半径 回文半径 以回文中心为起点 到回文串两端的距离 如 a b a 以b为回文中心 最长回文半径就是 4 可以根据个人习惯选择是否将回文中心包括
  • 题解 | #输出某一年的各个月份的天数#

    三方寄过去了 告诉我停止24届招聘 全部毁约 牛的 he芯 毁约应届生 34316 广西北部湾银行2022年校园招聘 广西北部湾银行股份有限公司2022届校园招聘 看终端大把大把15级的 这个14级是不是终端bg的白菜了 程序员面试六战六捷
  • uniapp-微信小程序分享给好友和朋友圈功能

    分享给好友 只需要在要分享的页面中设置 onShareAppMessage 即可 只有定义了此事件处理函数 右上角菜单才会显示 转发 按钮 监听用户点击页面内转发按钮 button 组件 open type share 使用button分享
  • nodejs+vue+ElementUi公司企业商品产品订购网站vue

    运行软件 vscode 前端nodejs vue ElementUi 语言 node js 框架 Express koa 前端 Vue js 数据库 mysql 开发软件 VScode webstorm hbuiderx均可企业现在正处于信
  • java SpringCloud版本b2b2c鸿鹄云商平台全套解决方案

    使用技术 Spring Cloud Spring Boot Mybatis 微服务 服务监控 可视化运营 B2B2C平台 平台管理端 包含自营 商家平台端 多商户入驻 PC买家端 手机wap 公众号买家端 微服务 30个通用微服务如 商品
  • 一招砍成本、四档提效率,建设智能工厂成就智造企业

    环境资源约束大 成本高 利润低是制约制造业发展的核心问题 日趋激烈的市场竞争环境又要求制造企业以更优的成本 更安全 更智能的方式提供更好的品质 更实时的响应 更高的效率 更个性化的产品 进退维艰的制造企业要如何破局 答案是 建智能工厂 成为
  • SpringBoot集成Redis

    依赖
  • 在区块链中看CHAT的独特见解

    问CHAT 谈谈对区块链以及区块链金融的理解 CHAT回复 区块链是一种去中心化的分布式数据库技术 这种技术通过加密算法 使数据在网络中传输和存储的过程变得更加安全可靠 区块链的出现引领了存储 交易等形式的革命 改变了诸多行业的运作模式 首
  • Python3 数据类型转换

    在Python3中 可以使用内置的函数来进行数据类型转换 以下是一些常用的数据类型转换函数 整数转换 int x 将x转换为整数 如果x是浮点数 会将其截断为整数 int x base 将x按照指定的进制base转换为整数 http www
  • 【手势识别】交警手势类型识别【含Matlab源码 3267期】

    博主简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 Matlab项目合作可私信 个人主页 海神之光 代码获取方式 海神之光Matlab王者学习之路 代码获取方式 座右铭 行百里者 半于九十 更多Matlab仿真内容点击 Matl
  • Python 循环语句的使用

    Python提供了多种循环语句 用于重复执行一段代码 以下是Python中常用的循环语句 for循环 for循环用于遍历一个可迭代对象 如列表 字符串 元组等 中的元素 执行指定的代码块 http www jshk com cn mb re
  • 云服务器和大宽服务器特点及应用场景

    大宽服务器和云服务器是两种不同类型的服务器 各有其特点和应用场景 首先 大宽服务器如其名所示 主要特点是具有较大的带宽 带宽越大 每秒可下载的数据量就越大 允许同时访问的客户数量也越多 因此 大宽服务器特别适合需要大量数据传输和高并发访问的
  • 【印刷数字识别】OCR识别系统【含Matlab源码 438期】

    博主简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 Matlab项目合作可私信 个人主页 海神之光 代码获取方式 海神之光Matlab王者学习之路 代码获取方式 座右铭 行百里者 半于九十 更多Matlab仿真内容点击 Matl
  • 【手写数字识别】BP神经网络手写数字识别【含GUI Matlab源码 868期】

    博主简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 Matlab项目合作可私信 个人主页 海神之光 代码获取方式 海神之光Matlab王者学习之路 代码获取方式 座右铭 行百里者 半于九十 更多Matlab仿真内容点击 Matl
  • LocalDateTime、LocalDate、Date的相互转换

    使用背景 LocalDateTime 及 LocalDate 是 Java8 的新特性 有时为了兼容 Date 类型需要进行转换 今天的项目就有一个需求是实现一个函数 能够计算出当天在一年中的第多少天 通过搜索找到java8有LocalDa
  • Python3 函数是什么

    在Python3中 函数是一段可重复使用的代码块 用于完成特定的任务 函数可以接受参数 并且可以返回结果 定义函数 在Python3中 可以使用def关键字来定义函数 函数的基本语法如下 def function name paramete
  • 白光迈克尔逊干涉仪

    摘要 白光干涉测量法是一种非接触式技术 用于精确测量 例如表面轮廓和微小位移 使用迈克尔逊干涉仪设置和氙灯光源 在VirtualLab Fusion中演示了白光干涉测量 考虑到光源的光谱特性 即有限的相干长度 结果显示仅当两个臂的路径长度几
  • 回溯算法第零篇【递归、搜索与回溯】【回溯算法入门必看】

    本篇文章的目的 1 给小伙伴们对回溯算法中的名词进行解释 2 消除递归的恐惧 回溯是递归的一个分支 给小伙伴们一个建议 整篇文章都要看完 一字不漏 全是干货 注意 分析回溯的思想之前 我们得知道一个关系 递归包含搜索 搜索包含回溯 所以我们