[算法]第一集 递归(未完待续)

news2024/9/23 22:33:55

递归啊递归,说简单简单,说难难。

首先我们要知道

一、什么是递归?

我们再C语言和数据结构里都用了不少递归,这里就不多详细介绍。

递归简单来说就是函数自己调用自己的情况

二、为什么要用递归呢?

本质来说其实就是我们在解决一个问题后出现相同的问题,解决这个问题后会再出现相同的问题。我们解决这些问题的方式一样,所以就出现了函数自己调用自己。

三、如何加深理解递归?

以下的步骤由浅入深

  1. 首先,你需要会画递归展开图
  2. 当你会画递归展开图时,下面要刷刷题,先从简单的二叉树中的题目来刷,这种一般比较容易
  3. 当上面都完成后,下面我们要做到的就是能够宏观的去看递归的过程,宏观的去看递归的过程需要:
    1. 不要一味的在意递归的过程
    2.  尽量把递归函数当作一个黑盒
    3. 相信这个黑盒的实力

四、如何写好一个递归

  1. 找到相同的问题(把主问题分解成若干个子问题)--->函数头的设计
  2. 只需要关心某一个子问题是如何解决得---->函数体的书写
  3. 注意递归函数的出口,避免死循环

五、题目实战

1,经典汉诺塔问题

面试题 08.06. 汉诺塔问题 - 力扣(LeetCode)

这道题属于是我们接触递归后解决的第一道问题,很多人做完汉诺塔后,知道了汉诺塔要用递归解决,那么你知道为什么汉诺塔要用递归吗?

1)如何解决汉诺塔问题

我们可以先假设,三个柱子为A、B、C,盘子数量问n,盘子开始在A上,我们需要把它放到C上。

当n=1时 我们只需要一次操作,把A上的盘子转移到C上。

当n=2时

我们需要把盘子全部转移到C上,所以我们需要先把大的盘子转移到C上,所以我们需要先把上面的盘子转移到B上,把A上最大的盘子转移到C上

当n=3时,此时A上右三个盘子,

我们要把A上的盘子全部移到C上,所以我们需要把A上最大的盘子先移动到C,所以我们需要把A上较小的两个盘子移到B上,这时我们可以把它转化成n=2来解,此时的C是B,B是C。

当我们想出这个思路时,我们的递归思路是不是来了呢?

2)为什么呢用递归

所以我们为什么要用递归呢?

因为我们解决这个汉诺塔问题时,我们可以把它分解成若干的子问题。

3)如何编写递归代码?

1.重复子问题->函数头

将x柱上的n个盘子,借助y柱,转移到z柱上——>void dfs(x,y,z,n)

2.只关心某一个子问题在做什么->函数体

我们只需要先移动上n-1个,即调用dfs(x,z,y,n-1),然后x——>z,然后dfs(y,x,z,n-1)

3.递归的出口

n=1时,x—— >z

4) 代码解决
class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) 
    {
        int n = A.size();
        dfs(n, A, B, C);
    }

    void dfs(int n, vector<int>& A, vector<int>& B, vector<int>& C)
    {
        if (n == 1)
        {
            C.push_back(A.back());
            A.pop_back();
            return;
        }

        dfs(n-1, A, C, B);    // 将A上面n-1个通过C移到B
        C.push_back(A.back());  // 将A最后一个移到C
        A.pop_back();          // 这时,A空了
        dfs(n-1, B, A, C);     // 将B上面n-1个通过空的A移到C
    }
};

如果对于代码有疑问的可以自己画画递归展开图

2.合并两个有序链表

1)题意解析

2)算法原理

解法:递归——>重复子问题

1)重复子问题——>函数头的设计

这个很明显,就是合并两个有序链表——>Node*dfs(l1,l2)

2)只关心某一个子问题在做什么->函数体

1.比大小

2.(假设l1较小)l1->next=dfs(l1->next,l2)

3.return l1

3)递归的出口

3)代码解决
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) {
            return l2;
        } else if (l2 == nullptr) {
            return l1;
        } else if (l1->val < l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        } else {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }
};

本题结束。

4)小总结

1)迭代(循环)和递归

它们都能解决重复的子问题,所以我们一般的代码都能递归改循环,循环改递归。

但是为什么有些代码递归改循环麻烦,有些代码循环改递归麻烦呢?

这个问题我们可以像看一下这个例子,比如汉诺塔问题吧,我们不是画过递归展开图吗?不少人肯定发现了,我们没的递归展开图和树的深度优先搜索极为相似。

可以这么说,递归展开图,其实就是对一棵树做一次深度优先遍历(dfs)

所以,我们可以得出当递归展开图,如上图,比较复杂时,这个时候递归改循环就比较困难!

那么什么时候递归改循环简单呢?我们根据上面的结论可以反推出来,当递归展开图简单时,递归改循环简单!如下图:

我们也可以举一个实例,比如遍历数组

假设我们有一个num数组

我们用循环写一个遍历并打印

for(int i=0;i<num.size();++i)
{
cout<<num[i[<<" ";
}

我们用递归写个函数呢?
 

void dfs(vector<int>& num,int i)
{
    if(i==num.size())
    return;
    cout<<num[i]<<" ";
    dfs(num,i+1)
}

3.反转链表

1)题意解析

2)算法原理

解法:递归——>重复子问题

本题我们可以从两个视角进行解决:

视角一:从宏观看待

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

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

相关文章

GIS赋能数字经济的地理脉络

在全球数字化转型的洪流中&#xff0c;数字经济以其惊人的速度与规模&#xff0c;重塑全球经济格局&#xff0c;成为推动社会进步的关键力量。地理信息系统&#xff08;GIS&#xff09;在数字经济的浪潮中扮演着不可替代的角色&#xff0c;它不仅是数字空间信息的集大动脉&…

用户管理①

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…

Vue.js 3.x 必修课|009|Watch API:响应式数据的侦听器(必读+实操)

欢迎关注公众号:CodeFit。 创作不易,如果你觉得这篇文章对您有帮助,请不要忘了 点赞、分享 和 关注,为我的 持续创作 提供 动力! 欢迎订阅《Vue 3.x 必修课| 2024》:http://t.csdnimg.cn/hHRrM 精品内容,物超所值(9.9 元,20+篇内容)。 1. 引言 在 Vue3 的 Composit…

基于 JWT 的模拟登录爬取实战

准备工作 1. 了解 JWT 相关知识 2. 安装 requests 库&#xff0c;并了解其基本使用 案例介绍 爬取网站&#xff1a; https://login3.scrape.center/ 用户名和密码是&#xff1a; admin 模拟登录 基于 JWT 的网站通常采用的是前后端分离式&#xff0c; 前后端的数据传输依…

【C++高阶】:自定义删除器的全面探索

✨ 我凌于山壑万里&#xff0c;一生自由随风起 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&am…

观测维度过大的一种ceres求解优化思路

详见 文章 这个优化如此重要&#xff0c;以至于需要单列一个文章。 使用场景&#xff1a; 比如lidar SLAM中优化点到面的距离&#xff0c;如果多个点关联到同一个面&#xff0c;那么就可以利用矩阵批量运算&#xff0c;假如有N个点&#xff0c;那么可以用一个factor来代替N个f…

【MYSQL】表操作

目录 查看当前数据库含有表查看表结构创建表插入&#xff08;新增create&#xff09;查询&#xff08;retrieve&#xff09;全列查询指定列查询查询列是表达式别名查询(as)去重查询(distinct)排序查询(order by)条件查询(where)比较/逻辑运算符使用 分页查询(limit) 一条语句各…

微服务-实现nacos的集群和Gateway网关的实现、认证校验、解决跨域

1. nacos的集群模式 1.1 分析 nacos在企业中的使用100%都是集群模式。需要掌握nacos集群的搭建 nacos的数据存放在derby本地磁盘中&#xff0c;nacos集群模式会导致数据库数据不一致&#xff0c;使用加一层思想&#xff0c;修改nacos的数据库&#xff0c;使用mysql数据库&…

kafka producer metrics

背景 做online Service埋点设计&#xff0c;塞了很多节点&#xff0c;采用了base64压缩&#xff0c;希望能监控当前消息的大小&#xff0c;防止超过threshold后无法正常发送。 kafka基本架构 producer metrics 官方文档 其中有两个参数用来表征在kafka的producer的client里&…

鸿蒙AI功能开发【hiai引擎框架-主体分割】 基础视觉服务

hiai引擎框架-主体分割 介绍 本示例展示了使用hiai引擎框架提供的主体分割能力。 本示例模拟了在应用里&#xff0c;选择一张图片&#xff0c;识别其图片中的显著性主体并展示出来主体的边界框的数据。 需要使用hiai引擎框架通用文字识别接口hms.ai.vision.subjectSegmenta…

加密软件有哪些常见的安全特性

1. 数据加密 核心功能&#xff1a;加密软件的核心在于对数据进行加密处理&#xff0c;通过复杂的加密算法&#xff08;如AES、RSA等&#xff09;将明文数据转换为密文&#xff0c;确保数据在存储和传输过程中的安全性。 透明加密&#xff1a;部分加密软件支持透明加密功能&am…

函数实例讲解(六)

文章目录 如何加密电话号码&#xff1f;&#xff08;SUBSTITUTE、REPLACE&#xff09;1、SUBSTITUTE2、REPLACE 用REPT函数做图表学生的考试成绩用A、B、C表示&#xff0c;如何找出哪个等级的学生最多呢&#xff1f;&#xff08;CHAR、CODE、MODE&#xff09;1、CHAR2、CODE3、…

【数据结构】顺序结构实现:特殊完全二叉树(堆)+堆排序

二叉树 一.二叉树的顺序结构二.堆的概念及结构三.堆的实现1.堆的结构2.堆的初始化、销毁、打印、判空3.堆中的值交换4.堆顶元素5.堆向上调整算法&#xff1a;实现小堆的插入6.堆向下调整算法&#xff1a;实现小堆的删除7.堆的创建1.堆向上调整算法&#xff1a;建堆建堆的时间复…

使用Go语言绘制折线统计图教程

使用Go语言绘制折线统计图教程 在本教程中&#xff0c;我们将学习如何使用Go语言及gg包绘制折线统计图&#xff0c;并将图表保存为PNG格式的图片。折线图适用于展示数据的变化趋势&#xff0c;并能直观地展示数据随时间或其他指标的变化。 安装gg包 首先&#xff0c;确保你已…

⌈ 传知代码 ⌋ 改进表情识别

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

Unity入门2——编辑器常用功能

点击文件夹&#xff0c;右键&#xff0c;选择showInExplorer可以在文件管理器中打开 选中多个图片素材&#xff0c;在Inspector里将Texture Type设置为Sprite(2D and UI)即可将图片素材用于UI 右键Hierachy面板的空白区&#xff0c;点击UI->Panel可以创建UI面板&#xf…

GPT-SoVITS-文本转语音(你的声音不再是唯一)

本文将要介绍GPT-SoVITS的安装和使用方法 首先感谢花儿不哭大佬带来的RVC声音克隆 花儿不哭&#xff1a; 花儿不哭的个人空间-花儿不哭个人主页-哔哩哔哩视频 (bilibili.com) GPT-SoVITS下载地址 GitHub - RVC-Boss/GPT-SoVITS: 1 min voice data can also be used to train a …

网络药理学:分子对接之pocasa/proteins.plus/Deepsite网站预测蛋白口袋

前言 配体的结合需要疏水作用&#xff0c;通常来说&#xff0c;疏水性空腔&#xff08;开口小、肚子大、能容纳一定体积的分子结构&#xff09;更有可能成为口袋。当我们复现网络药理学文章时可能经过前面的筛选&#xff0c;依旧有数个乃至数十个蛋白需要做分子对接验证。此时如…

算法——动态规划:基础

文章目录 一、基本介绍二、案例——斐波那契数列1. 基本介绍2. 递归实现3. 动态规划3.1 重叠子问题3.2 最优子结构3.3 无后效性3.4 性质的总结 4. 使用 动态规划 的思想实现4.1 自顶向下 的 递归4.2 自底向上 的 递推4.3 两种思路的简单比较 三、总结 一、基本介绍 动态规划&a…

python语言day4 函数 生成器yield、next关键字 装饰器

一、 函数 定义&#xff1a; def info(): print("执行info()函数") 直接调用方法和封装一个函数&#xff1a; 使用信息发送的功能为例 登录163网易免费邮-你的专业电子邮局 1&#xff09;开启POP3/SMTP服务&#xff0c;会得到对应的授权码&#xff0c;也就是登陆…