搜索回溯算法(DFS)1------递归

目录

简介:

递归问题解题的思路模板

例题1:汉诺塔

例题2:合并两个有序链表

例题3:反转链表

例题4:两两交换链表中的节点

例题5:Pow(x,n)-快速幂

结语:


简介:

本系列将会带大家深入理解搜索中的一大分支深搜,深搜是离不开递归的和回溯思想的(优化需要剪枝),故我会在例题中详细指出解决这一系列问题的思考思路和解题技巧。

那么我们就从递归开始(深搜的基础)也就是本文中主要介绍的。

什么是递归?

简单来说就是函数自己调用自己。

为什么会用到递归?

大问题可以拆解成相同的子问题,且子问题的解法和大问题的一模一样,这是就可以用到递归。

在解决⼀个规模为n的问题时,如果满⾜以下条件,我们可以使用递归来解决:

a. 问题可以被划分为规模更⼩的⼦问题,并且这些⼦问题具有与原问题相同的解决⽅法。

b. 当我们知道规模更⼩的⼦问题(规模为n-1)的解时,我们可以直接计算出规模为n的问题的解。

c. 存在⼀种简单情况,或者说当问题的规模⾜够⼩时,我们可以直接求解问题。

⼀般的递归求解过程如下:

a. 验证是否满⾜简单情况。

b. 假设较⼩规模的问题已经解决,解决当前问题。

上述步骤可以通过数学归纳法来证明。

如何理解递归?

不要太在意细节,相信函数。 

递归问题解题的思路模板

当然在设计递归函数之前最重要的是你要你的递归函数干嘛。

1.递归函数的作用

2.相同子问题------------函数头

3.只关心某一个子问题是如何解决的------------函数体

4.递归出口

建议友友在写递归类型的题目是一定要把这三个地方考虑清楚了再下手。

最后就是相信函数。

例题1:汉诺塔

链接:汉诺塔

题目简介:

递归问题非常经典的一道题目,在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

解法:

我们可以看到每次都可以把大问题分解成相同的子问题,且子问题的解决方法和大问题的一模一样故我们可以使用递归来处理。 

1.递归函数的作用

函数作⽤:将A中的上⾯n个盘⼦挪到C中。这里的A和C是函数参数的A和C不是实际的(很重要)。

2.相同子问题(函数头)

我们要设计一个函数头来完成汉诺塔的递归过程,我们可以看到我们需要三根柱子和要记录下来还剩下几个盘子。故我们的函数头可以设计成public void dfs(List<Integer> a, List<Integer> b, List<Integer> c, int n)。关于List<Integer>如果友友还没有学到的话可以把他看成一个数组。

3.只关心某一个子问题是如何解决的(函数体)

我们取第三层汉诺塔来研究(大问题被拆成3层汉诺塔)。

我们发现子问题刚来三件事

1.把A上面n - 1 个盘子通过C移动到B 

2.把A上面最后一个盘中移动到C

3.把B上面n - 1个盘中通过A 移动到C

dfs(a, c, b, n - 1);

c.add(a.remove(a.size() - 1));//这里是因为给出的例题这样做就是把盘中从A移动到C(理解思路即可)

dfs(b, a, c, n - 1);

4.递归出口

当问题的规模变为n=1时,即只有⼀个盘⼦时,我们可以直接将其从A柱移动到C柱。

本例题代码实现如下:

class Solution {public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {dfs(A,B,C,A.size());}public void dfs(List<Integer> A, List<Integer> B, List<Integer> C,int n ){if(n == 1){C.add(A.remove(A.size() - 1));return;}dfs(A,C,B,n - 1);C.add(A.remove(A.size() - 1));dfs(B,A,C,n - 1);}
}

关于本例题要注意的点:c.add(a.remove(a.size() - 1));可能有的友友会纠结为什么不是remove(0)呢,其实自己模拟一下即可,我们移走盘子是从最上面那个盘子开始移动的。

不用太深究函数的细节(陷入将无法自拔),如果是第一次的话可以去b站上看看递归的全过程细节(这里的不用深究是建立在已经对它的展开有一定理解了,第一次学汉诺塔的话我还是建议大家可以看看别人推的整个过程,理解更加深刻)。

例题2:合并两个有序链表

链接:合并两个有序链表

题目简介:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

解法:

通过分析题目我们发现可以把大问题拆成下图的子问题,上面的1已经合并有序现在要让2,4和下面链表合并有序。

故我们可以用递归来解决这道问题。

1.递归函数的作用

交给你两个链表的头结点,你帮我把它们合并起来,并且返回合并后的头结点.

2.相同子问题(函数头)

由上图可以看到函数要包含两个链表还要能返回合并后的链表故函数头设定为:public ListNode mergeTwoLists(ListNode l1, ListNode l2)

3.只关心某一个子问题是如何解决的(函数体)

选择两个头结点中较小的结点作为最终合并后的头结点,然后将剩下的链表交给递归函数去处理。

4.递归出口

当某⼀个链表为空的时候,返回另外⼀个链表。

代码如下:

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {if(list1 == null){return list2;}if(list2 == null){return list1;}if(list1.val <= list2.val){list1.next = mergeTwoLists(list1.next,list2);return list1;}else{list2.next = mergeTwoLists(list1,list2.next);return list2;}}
}

例题3:反转链表

链接:反转链表

题目简介:

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

解法:

要想让1到5逆序,可以让5逆序后让1到4逆序一直这样下去我们不难发现这就是递归。

1.递归函数的作用

交给你⼀个链表的头指针,你帮我逆序之后,返回逆序后的头结点。

2.相同子问题(函数头)

需要传入链表,5节点逆序后要把逆序后的新头节点返回故将函数体设为public ListNode reverseList(ListNode head)

3.只关心某一个子问题是如何解决的(函数体)

先把当前结点之后的链表逆序,逆序完之后,把当前结点添加到逆序后的链表后⾯即可。

4.递归出口

当前结点为空或者当前只有⼀个结点的时候,不⽤逆序,直接返回。

代码如下:

class Solution {public ListNode reverseList(ListNode head) {ListNode newHead = head;if(head == null){return head;}ListNode cur = head.next;ListNode prev = head;head.next = null;while(cur != null){ListNode next = cur.next;cur.next = prev;prev = cur;cur = next;}return prev;}
}

例题4:两两交换链表中的节点

链接:两两交换链表中的节点

题目简介:

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

 解法:

我们通过阅读题目可以发现要使整个链表两两交换 ,可以将大问题分为把1和2后面的节点两两交换,把一二交换即可,同理3和4也是同样的处理思路。

1.递归函数的作用

交给你⼀个链表,将这个链表两两交换⼀下,然后返回交换后的头结点;

2.相同子问题(函数头)

需要传入原始链表和返回新的头节点故设计为:public ListNode swapPairs(ListNode head)

3.只关心某一个子问题是如何解决的(函数体)

先去处理⼀下第⼆个结点往后的链表,然后再把当前的两个结点交换⼀下,连接上后面处理后的链表;

4.递归出口

当前结点为空或者当前只有⼀个结点的时候,不⽤交换,直接返回。

代码如下:

class Solution {public ListNode swapPairs(ListNode head) {if(head == null || head.next == null){return head;}ListNode newHead = head.next;head.next = swapPairs(head.next.next);newHead.next = head;return newHead;}
}

例题5:Pow(x,n)-快速幂

链接:Pow(x,n)

题目简介:

实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。

  解法:

这题不能使用1个1个数的分离递归(会超时),我们这里要采用二分的思路,具体实现如下:

1.递归函数的作用

求出x 的n 次⽅是多少,然后返回;

2.相同子问题(函数头)

需要传入需要n次方的x和n还要将其返回public double pow(double x, int n)

3.只关心某一个子问题是如何解决的(函数体)

先求出x 的n / 2 次⽅是多少,然后根据n 的奇偶,得出x 的n 次⽅是多少;

4.递归出口

当n 为0 的时候,返回1 即可。

代码如下:

最上面要区分一下正负数的区别即可。

class Solution {public double myPow(double x, int n) {return (n < 0) ? 1.0 / pow(x, - n) : pow(x , n);}public double pow(double x,int n){if(n == 0){return 1.0;}double tmp = pow(x,n / 2);return (n % 2 == 0) ? tmp * tmp : tmp * tmp * x;}
}

总结:本文章是搜索回溯的第一篇,带大家再复习了一下递归,后续的章节会带领大家深度理解深搜和回溯算法。

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/719752.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式驱动学习第二周——断言机制

前言 这篇博客来聊一聊C/C的断言机制。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&#xff0c;一起讨论一起学习。现在关注就是老粉啦&#xff01; 目录 前言1. 断言介绍…

贪心 Leetcode 134 加油站

加油站 Leetcode 134 学习记录自代码随想录 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发&#xff0c;开始时油…

串联所有单词的子串

题目链接 串联所有单词的子串 题目描述 注意点 words[i] 和 s 由小写英文字母组成1 < words.length < 5000可以以 任意顺序 返回答案words中所有字符串长度相同 解答思路 根据滑动窗口哈希表解决本题&#xff0c;哈希表存储words中所有的单词及单词的出现次数&#…

p18 线性代数,行阶梯型矩阵

行阶梯型矩阵 行最简型矩阵

steam游戏搬砖,跨国信息差项目,每天1小时收益也很不错

大家好&#xff0c;我是阿阳&#xff01;每天都是一个新的开始&#xff01; 今天看到个Steam游戏搬砖项目&#xff0c;还是跨国国际贸易&#xff0c;感觉很好玩&#xff0c;特来给大家分享。 原理简介 就是把Steam上的游戏装备&#xff0c;搬运到国内网易Buff平台上来卖。目前…

算法沉淀——动态规划之01背包问题(leetcode真题剖析)

算法沉淀——动态规划之01背包问题 01.【模板】01背包02.分割等和子集03.目标和04.最后一块石头的重量 II 01背包问题是一类经典的动态规划问题&#xff0c;通常描述为&#xff1a;有一个固定容量的背包&#xff0c;以及一组物品&#xff0c;每件物品都有重量和价值&#xff0c…

云计算 2月28号 (linux的磁盘分区)

一 存储管理 主要知识点: 基本分区、逻辑卷LVM、EXT3/4/XFS文件系统、RAID 初识硬盘 机械 HDD 固态 SSD SSD的优势 SSD采用电子存储介质进行数据存储和读取的一种技术&#xff0c;拥有极高的存储性能&#xff0c;被认为是存储技术发展的未来新星。 与传统硬盘相比&#xff0c…

深度伪造,让网络钓鱼更加难以辨别

网络钓鱼一直是安全领域的一个突出话题&#xff0c;尽管这类诈骗形式已经存在了几十年&#xff0c;依旧是欺诈攻击或渗透组织的最有效方法之一。诈骗分子基于社会工程原理&#xff0c;通过邮件、网站以及电话、短信和社交媒体&#xff0c;利用人性&#xff08;如冲动、不满、好…

嵌入式驱动学习第二周——Linux内核打印

前言 这篇博客来聊一聊Linux内核打印。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&#xff0c;一起讨论一起学习。现在关注就是老粉啦&#xff01; 目录 前言1. dmesg指令…

【LeetCode:225. 用队列实现栈 + 栈 | 队列】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

水牛社软件是真的吗?

软件是真的&#xff0c;不过毕竟是为了赚钱或者获取资源而买的&#xff0c;所以大部分只关心能赚多少钱吧 说实话&#xff0c;我用了2年了&#xff0c;一些独立的项目还有群&#xff0c;有一月挣几千上万的&#xff0c;有一月赚几百的 软件是一个集合体&#xff0c;不是像很多…

代码随想录第二十七天 455.分发饼干 376.摆动序列 53.最大子序和 122.买卖股票的最佳时机II

LeetCode 455 分发饼干 题目描述 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼…

2024全国护网行动HW行动招聘/收人!!!

2024全国护网行动HW行动招聘 溯蓉信创开始收人啦&#xff01;&#xff01;&#xff01;现在开始收录2024HW简历&#xff0c;感兴趣的小伙伴扫码二维码添加微信 我们签约后&#xff0c;入场即预付款3k&#xff0c;签约后我们会在HW之前对我们的人员进行HW培训&#xff0c;保证上…

Three.js--》探寻Cannon.js构建震撼的3D物理交互体验(一)

我们用three.js可以绘制出各种酷炫的画面&#xff0c;但是当我们想要一个更加真实的物理效果的话&#xff0c;这个时候我们就需要一个物理的库&#xff0c;接下来我们就讲解一下今天要学习的canon&#xff0c;它可以给我们提供一个更加真实的物理效果&#xff0c;像物体的张力、…

YOLOv8姿态估计实战:训练自己的数据集

课程链接&#xff1a;https://edu.csdn.net/course/detail/39355 YOLOv8 基于先前 YOLO 版本的成功&#xff0c;引入了新功能和改进&#xff0c;进一步提升性能和灵活性。YOLOv8 同时支持目标检测和姿态估计任务。 本课程以熊猫姿态估计为例&#xff0c;将手把手地教大家使用C…

MSCKF5讲:后端代码分析

MSCKF5讲&#xff1a;后端代码分析 文章目录 MSCKF5讲&#xff1a;后端代码分析1 初始化initialize()1.1 加载参数1.2 初始化IMU连续噪声协方差矩阵1.3 卡方检验1.4 接收与订阅话题createRosIO() 2 IMU静止初始化3 重置resetCallback()4 featureCallback4.1 IMU初始化判断4.2 I…

【文末送书】智能计算:原理与实践

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的停车位检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发停车位检测系统对于优化停车资源管理和提升用户体验至关重要。本篇博客详细介绍了如何利用深度学习构建一个停车位检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并结合了YOLOv7、YOLOv6、YOLOv5的性能对比&#xf…

HarmonyOS端云体化开发—创建端云一体化开发工程

云开发工程模板 DevEco Studio目前提供了两种云开发工程模板&#xff1a;通用云开发模板和商城模板。您可根据工程向导轻松创建端云一体化开发工程&#xff0c;并自动生成对应的代码和资源模板。在创建端云一体化开发工程前&#xff0c;请提前了解云开发工程模板的相关信息。 …

前端学习之HTML(第一天)

什么是HTML HTML是一种用来描述网页的一种语言&#xff0c;HTML不是一种编程语言&#xff0c;而是一种标记语言。 HTML标签 HTML 标签是由尖括号包围的关键词&#xff0c;比如 <html> HTML 标签通常是成对出现的&#xff0c;比如 <b> 和 </b> 标签对中的…