宏观角度认识递归之汉诺塔问题

宏观角度认识递归 

听到递归,不少人都会对此充满些迷惑,今天我们就从不同的角度来认识递归,消除恐惧。

递归,简单来说,就是函数自己调用自己的情况,也就是在一个主问题中,我们会引申出一个相同的子问题,子问题继续引申下去,还是一个相同的子问题; 

此处以二叉树中的后序遍历来借以理解:要先对根结点的左节点和右节点依次遍历,然后再遍历自身节点;

1. 将 1 作为根结点,依次遍历其左子树和右子树,再遍历 1 ;

2. 将 2 作为根结点,依次遍历其左子树和右子树,再遍历 2 ;

3. 将 4 作为根结点,依次遍历其左子树和右子树,再遍历 4 ;

......

类似于这种情况,每一个子问题,都是与主问题类似的,也就是每个子问题的执行方法都是相同的,就可以运用到递归了;

认识了递归后,我们要学会从另外一个角度来看递归:宏观角度看待递归的过程,以往的情况我们可能都会去画图来帮助理解,这也是一种好办法,但有时候会局限于这个思维;

所谓的宏观角度看待递归可以理解为三个点:

1. 不要太在意递归的细节展开图;

2. 把递归的函数当成一个黑盒;

3. 要坚信这个黑盒函数一定可以完成任务;

利用宏观角度思想来写递归:

1. 找到相同的子问题 -> 定义出函数头;

2. 针对一个子问题来理解是如何解决的 -> 定义出函数体;

3. 针对函数的出口做一下出口,避免死循环;

利用这个思想,对于二叉树的后序遍历来写一个伪代码:

1. 对于二叉树的后序遍历,它的主问题和子问题都是对于一个根结点,进行左子树遍历,然后右子树遍历,最后根结点自身遍历,因此这个问题就需要到了根结点的位置,才有办法去找到左右子树的位置从而去遍历,所以函数头可以定义为:void dfs(TreeNode* root);

2. 通过上述对于子问题的描述,我们就要先对左子树遍历,然后右子树遍历,最后遍历自身节点,因此函数体可以这样来定义:dfs(root->left); dfs(root->right); printf(root-val); 此处就体现了宏观思想了,要对这个函数当成一个黑盒的,不用去过于在意它的细节展开;

3. 最后要考虑函数的出口,也就是当节点为 null 的时候,要直接return,因此添加条件:

if(root == null) return;

 所以伪代码可以写为:

void dfs(TreeNode* root)
{
    if(root == null) return;
    dfs(root ->left);
    dfs(root -> right);
    printf(root->val);
}

 汉诺塔问题

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

先考虑圆盘为 1,2 两种情况进行分析:当圆盘数量为 1 的时候,可以直接放到 C 柱子上;

当圆盘数量为 2 的时候,就需要借助到 B 柱子来完成摆放了; 

再考虑圆盘为 3 的情况进行分析:当圆盘数量为 3 的时候,观察下图,我们可以看出具体的流程:先将上面的两个盘子借助 C柱子 摆放到 B柱子上,然后最大的盘子再到 C 柱子上,最后 B 柱子上的两个盘子,再借助于 A 柱子回到 C 柱子上;

此时仔细思考,三个圆盘的时候, 要对最顶上的两个圆盘进行放置于 B 位置,这个操作就相当于当圆盘为 2 的时候的操作了。此时主问题的解决办法就和子问题的解决方法形成相似的情况了,也就是可以使用递归了。

因此,当有 n 个圆盘的时候,统一的解决办法都是如此:

1. A柱子上的 n-1 个圆盘借助于 C柱子,放到 B柱子上;

2. A柱子底下最大的圆盘放到 C柱子上;

3. B柱子上的圆盘借助于 A柱子放到 C柱子上;

1. 针对重复的子问题,定义函数头:

bfs(List<Integer> A, List<Integer> B, List<Integer> C,int n)

A,B,C 集合依次表示A集合借助于B集合移动到C集合上 + 针对A集合上n个圆盘进行移动;

2. 针对子问题进行理解,定义函数体:

 2.1 将 A 上的 n-1 个圆盘借助于 C 移到 B 上:bfs(A,C,B,n-1);

 2.2 将 A 上的最后一个圆盘移到 C 上;

 2.3 将 B上的 n-1 个圆盘借助于 A 移到 C上:bfs(B,A,C,n-1);

3. 考虑出口的设计:

此时就要考虑圆盘数为 1 时的处理方式:将 A 上的圆盘直接放置于 C 上; 

完成代码 

class Solution {
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        bfs(A,B,C,A.size());
    }
    public void bfs(List<Integer> A, List<Integer> B, List<Integer> C,int n){

        // 出口设计,当只有一个圆盘的时候,直接从 A 移动到 C
        if(n == 1){
            C.add(A.remove( A.size() - 1 ));
            return;
        }

        bfs(A,C,B,n-1);     // 1. 将 A 上的 n-1 个圆盘借助 C 放置 B 上

        // 注意此处 A 的最后一个圆盘不能直接写 [0]
        // 因为在递归的过程中,针对的是某个子问题
        C.add(A.remove( A.size() - 1 ));     // 2. 将 A 上的最后一个圆盘,放到 C 上

        bfs(B,A,C,n-1);     // 3. 将 B 上的 n-1 个圆盘借助 A 放到 C 上

    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32-电源管理(实现低功耗)

电源管理 STM32 HAL库对电源管理提供了完善的函数和命令。 工作模式&#xff08;高功耗->低功耗&#xff09;&#xff1a;运行、睡眠、停止、待机。 若备份域电源正常供电&#xff0c;备份域内的RTC都可以正常运行&#xff0c;备份域内的寄存器的数据会被保存&#xff0c;不…

家用洗地机哪个牌子质量最好?家用洗地机推荐

洗地机也就是集吸尘器&#xff0c;拖地&#xff0c;洗地&#xff0c;功能于一体的家电&#xff0c;无论干湿垃圾都能清理的干干净净&#xff0c;而且还不用弯腰&#xff0c;有的只用换个头&#xff0c;就从拖地变成了吸尘器和除螨仪简直就是清洁家里卫生的打扫神器啦!那么面对市…

Spring-Spring 之底层架构核心概念解析

BeanDefinition BeanDefinition表示Bean定义&#xff0c;BeanDefinition中存在很多属性用来描述一个Bean的特点。比如&#xff1a; class&#xff0c;表示Bean类型scope&#xff0c;表示Bean作用域&#xff0c;单例或原型等lazyInit&#xff1a;表示Bean是否是懒加载initMeth…

chatgpt接口调用

在线接口文档&#xff1a; https://app.apifox.com/invite?tokensymrLP7sojF6N31kZqnpZ 接口地址 https://chat.xutongbao.top/api/light/chat/createChatCompletion 请求方式 POST 请求参数 token String, 必须 prompt Array, 必须 例子一&#xff1a; 包含上下文 [ { "…

行政处罚类型有哪些?哪里能够查到一家企业的行政处罚信息?

在查询企业信息的时候&#xff0c;处理企业基础的工商信息之外&#xff0c;我们还会注意到到的就是企业的处罚信息。毕竟处罚可以直观反应出一个企业的违法违规行为&#xff0c;帮助我们直接了解企业。 那么&#xff0c;企业的行政处罚包括哪些内容呢&#xff1f; 根据《中华…

【MATLAB源码-第66期】基于麻雀搜索算法(SSA)的栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 麻雀搜索算法&#xff08;Sparrow Search Algorithm, SSA&#xff09;是一种新颖的元启发式优化算法&#xff0c;它受到麻雀社会行为的启发。这种算法通过模拟麻雀的食物搜索行为和逃避天敌的策略来解决优化问题。SSA通过模拟…

Macroscope安全漏洞检测工具简介

学习目标&#xff1a; 本介绍旨在帮助感兴趣者尽快了解 Macroscope&#xff0c;这是一款用于安全测试自动化和漏洞管理的企业工具。 全覆盖应用程序安全测试&#xff1a; 如下图所示&#xff0c;如果使用多种互补工具&#xff08;SAST/DAST/SCA 等&#xff09;来检测应用程序…

网络取证-Tomcat-简单

题干&#xff1a; 我们的 SOC 团队在公司内部网的一台 Web 服务器上检测到可疑活动。为了更深入地了解情况&#xff0c;团队捕获了网络流量进行分析。此 pcap 文件可能包含一系列恶意活动&#xff0c;这些活动已导致 Apache Tomcat Web 服务器遭到破坏。我们需要进一步调查这一…

解决uniapp的video标签和transition属性使用时出现错位的问题

template&#xff1a;三个视频都每个占满屏幕&#xff0c;点击按钮滚动最外层bgBox元素&#xff0c; style: 想要加上动画过渡效果&#xff1a; 这是显示第一个视频&#xff1a; 点按钮向上滑动滚动到第二个视频时&#xff1a; 视频错位了 &#xff0c;因为视频消失又出现的时候…

这两天公司面了一个字节来的要求月薪23K,明显感觉他背了很多面试题...

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…

泡泡玛特首度跨界超跑品牌兰博基尼汽车,以潮流基因探索时空边界

近期&#xff0c;泡泡玛特携手兰博基尼汽车&#xff0c;于上海国际赛车场进行了一场玩味十足的赛道体验。25位兰博基尼车主&#xff0c;及多位汽车领域知名媒体人、kol到场参与。兰博基尼跑车巡游、专业车手驾驶的兰博基尼涂装赛车试乘、MEGA SPACE MOLLY 1000%/400%兰博基尼汽…

【Amazon】AWS实战 | 快速发布安全传输的静态页面

文章目录 一、实验架构图二、实验涉及的AWS服务三、实验操作步骤1. 创建S3存储桶&#xff0c;存放网站网页2. 使用ACM建立域名证书3. 设置Cloudfront&#xff0c;连接S3存储桶✴️4. 设置Route53&#xff0c;解析域名服务5. 通过CLI工具上传网页更新内容【可选】 四、实验总结 …

CentOS、linux安装squid搭建正向代理,window11配置正向代理

1.CentOS安装配置squid 1.1.安装 yum install -y squid1.2.修改配置文件 在配置文件添加以下2行代码 acl localnet src 0.0.0.0/0.0.0.0 # add by lishuoboy http_access allow all # add by lishuoboy1.3.启动squid systemctl restart squid2.win11…

node复制当前目录下的文件夹到另一层目录(包含多层文件夹嵌套)

前段时间在跟进node项目时有个node项目的需求&#xff0c;然后上线流程是把前端build后的文件夹放到后端仓库的静态资源目录下&#xff0c;再把后端代码发布上线。这样做的好处是在前端页面调用接口时&#xff0c;可以直接 /xxx来调用&#xff08;浏览器会自动把域名补全&#…

基于仿真的飞机ICD工具测试

机载电子系统是飞机完成飞行任务的核心保障之一。从1949年新中国建立至今70余年的发展过程中&#xff0c;随着我国在航空航天领域的投资逐年增多&#xff0c;机载电子系统大致经历了四个发展过程阶段&#xff0c;按照出现的先后顺序进行排序&#xff0c;分别为&#xff1a; 1、…

Springboot使用EasyExcel导入导出Excel文件

1&#xff0c;准备Excel文件和数据库表结果 2&#xff0c;导入代码 1&#xff0c;引入依赖 <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifac…

掌握微信批量添加好友技巧,让你的社交更高效

微信作为当今的热门通讯工具&#xff0c;在企业营销中扮演着越来越重要的角色。然而&#xff0c;微信并没有提供自动批量添加好友的功能&#xff0c;给运营者带来了不小的挑战。一个个手动添加不仅耗时&#xff0c;而且频繁操作还容易导致账号被封。本文将介绍几种手动批量添加…

PHP foreach 循环跳过本次循环

$a [[id>1],[id>2],[id>3],[id>4],[id>5],[id>6],[id>7],[id>18],];foreach($a as $v){if($v[id] 5){continue;}$b[] $v[id];}return show_data(,$b); 结果&#xff1a;

Linux软件安装包管理器yum

Linux软件安装 Linux软件安装的本质 ​ 对于安装软件最基本的理解就是把可执行程序拷贝到指定路径下&#xff0c;我们知道直接输入指令就可以实现想要的功能&#xff0c;这些指令本质上都是放在指定路径下的可执行文件&#xff0c;如果我们把写好的程序编译后的可执行文件放到…

dubbo没有找到生产者

1、没有找到生产者 com.alibaba.dubbo.rpc.RpcException: No provider available from registry 127.0.0.1:2181 for service .... , please check status of providers(disabled, not registered or in blacklist)2、 查看是不是 对应的providers 没有 注册上去 找到 zk 对应…