汉诺塔 --- 递归回溯算法练习一

目录

1. 什么叫汉诺塔

2. 分析算法原理

2.1. 当盘子的数量为1

 2.2. 当盘子的数量为2

2.3. 当盘子的数量为3时

3. 编写代码

3.1. 挖掘重复子问题

3.2. 只关心某一个子问题如何处理

3.3. 递归的结束条件

3.4. 代码的编写

4. 递归展开图分析


1. 什么叫汉诺塔

力扣上的原题链接如下:

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

什么叫汉诺塔呢?

汉诺塔是一种经典的数学智力游戏,它起源于印度。游戏中有三个竖立的柱子,通常称为"A"、“B”、“C”。最初,所有的圆盘按照从大到小的顺序叠放在"A"柱子上,最大的圆盘在底部,最小的圆盘在顶部。游戏的目标是将所有的圆盘从"A"柱子移动到"C"柱子上,但在移动过程中要遵守以下规则:

  1. 一次只能移动一个圆盘;
  2. 每次移动必须将一个圆盘从柱子的顶部移到另一个柱子的顶部;
  3. 移动过程中,大圆盘不能放在小圆盘的上面。

通过按照规则逐个移动圆盘,最后把所有圆盘都移动到"C"柱子上就完成了游戏。汉诺塔问题被广泛用作数学问题和编程算法的练习。它展示了递归算法的应用,因为解决汉诺塔问题的常用方法就是利用递归。

2. 分析算法原理

2.1. 当盘子的数量为1

初始情况如下:

此时只需要将A柱子的盘子直接移动到C柱子上即可。 

 2.2. 当盘子的数量为2

初始情况如下:

我们的目的是,将这两个盘子从A柱子移动到C住柱子。而要想将a盘子移动到C柱子上,那么首先要将b移动到B柱子上。

此时我们可以分为三个过程:

step 1:将b盘子以C柱子为辅助,移动到B柱子。

step 2:将a盘子直接移动到C柱子。

step 3:将b盘子以A柱子为辅助,移动到C柱子。

step 1:

将b盘子以C柱子为辅助,移动到B柱子

 

step 2:

将a盘子直接移动到C柱子

 

step 3:

将b盘子以A柱子为辅助,移动到C柱子

此时经过上面的三个过程就达到了我们的目的。

2.3. 当盘子的数量为3时

我们的目的是,将这三个盘子从A柱子移动到C住柱子。而要想将a盘子移动到C柱子上,那么首先要将a上面的柱子(把b和c看作为一个整体)移动到B柱子上。此时将b和c移动到B柱子上不就是当盘子数量为2吗,因此此时我们依旧可以分为三个过程:

step 1:将b和c盘子以C柱子为辅助,移动到B柱子。

step 2:将a盘子直接移动到C柱子。

step 3:将b和c盘子以A柱子为辅助,移动到C柱子。

step 1:将b和c盘子以C柱子为辅助,移动到B柱子

step 2: 将a盘子直接移动到C柱子。

step 3: 将b和c盘子以A柱子为辅助,移动到C柱子

以此类推,我们发现,对于一个大问题,是可以被分为若干个相同类型的子问题,而这就是能用递归的原因。

那么我们的总结就是:

递归结束条件: 当盘子的数量 == 1时,直接处理; 

递归中间过程: 当盘子的数量 >= 2时,我们分三个步骤处理; 

我们将最下面的盘子称之为 Last; Last上面的所有盘子称之为 All

step 1: 将A柱子 "Last" 的 "All"  借助C柱子 移动到 B柱子。

step 2: 将A柱子 "Last" 直接移动到 C柱子上。

step 3: 将B柱子 "ALL" 借助 A柱子 移动到 C柱子上。

3. 编写代码

既然可以用递归处理,那么如何编写递归代码呢?我们可以分为三个步骤。

3.1. 挖掘重复子问题

这个步骤决定了递归的函数头,将问题抽象为函数头

汉诺塔的重复子问题:

将A柱子上的一堆盘子,以B柱子为辅助,移动到C柱子。

// 函数头如下:
// A、B、C 分别代表三个柱子
// n代表你要将几个盘子从A柱子,以B盘子为辅助,移动到C柱子
void _hanota(A,B,C,n);

3.2. 只关心某一个子问题如何处理

这个步骤决定了递归的函数体。这一步只需要关注某一个子问题如何处理的,经过我们的分析算法原理,我们得知了任何一个子问题可以被分为三个过程,如下:

我们将最下面的盘子称之为 LastLast上面的所有盘子称之为 All

step 1: 将A柱子 "Last" 的 "All"  借助C柱子 移动到 B柱子。

step 2: 将A柱子 "Last" 直接移动到 C柱子上。

step 3: 将B柱子的 "ALL" 借助 A柱子 移动到 C柱子上。

//step 1: 将A柱子 "Last" 的 "All"  借助C柱子 移动到 B柱子。
void _hanota(A,C,B,n-1);
//step 2: 将A柱子 "Last" 直接移动到 C柱子上。
A.back() --->  C
//step 3: 将B柱子上的 "ALL" 借助 A柱子 移动到 C柱子上。
void _hanota(B,A,C,n-1);

3.3. 递归的结束条件

这个步骤决定了递归的出口,如何判定呢? 当一个问题不可以在被分为相同类型的子问题时此时就是递归的结束条件

经过我们前面的分析,当盘子的数量 == 1时,直接处理,此时就是递归的结束条件。

if(n == 1)
    return ;

3.4. 代码的编写

有了上面的分析,代码就非常简单了:

class Solution {
public:

    void _hanota(vector<int>& A, vector<int>& B, vector<int>& C,size_t n)
    {
        // 递归出口
        if(n == 1)
        {
            C.push_back(A.back());
            A.pop_back();
            return ;
        }
        // step 1:
        _hanota(A,C,B,n-1);
        // step 2:
        C.push_back(A.back());
        A.pop_back();
        // step 3:
        _hanota(B,A,C,n-1);
    }

    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
        _hanota(A,B,C,A.size());
    }
};

4. 递归展开图分析

为了更好地理解上面的代码,我们试画一下当N == 3时的递归展开图。同样,为了更好地画递归图,我们将递归出口的逻辑以  ’#‘ 表示,step 1、step 2、step 3、 分别以 (1)、(2)、(3)表示。

经过我们上面的函数的左边的递归展开图,我们应该可以了解它的过程了,当我们以宏观角度看,认为把A柱子上的b和c这两个盘子经由C柱子辅助移动到B柱子,是一个步骤;但是递归展开后,我们发现,每次当函数的盘子数量1时,才会移动盘子(而且移动的最上面的盘子)。所以我们的代码中移动的是A.back(),最后一个元素,而不是A[0]。

至此,我们的汉诺塔就此结束。

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

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

相关文章

iOS代码混淆----自动

先大致解释一下“编译"、"反编译": 编译&#xff1a;就是把千千万万行字符串(也叫代码&#xff0c;或者源文件)&#xff0c;变成010101010101(机器码&#xff0c;也叫目标代码) 编译过程&#xff1a;预处理-编译-汇编-链接 我的脚本运行在预处理阶段。 反编…

【自动控制原理】时域分析法:稳定性分析(稳)、误差分析和计算(准)

文章目录 第3章 时域分析法3.1 基本概念3.2~4 一阶、二阶、高阶系统的时间响应及动态性能3.6 稳定性分析——稳3.6.1. 稳定性的定义3.6.2 稳定性的条件3.6.3 劳斯稳定判据首列出现0&#xff0c;但该行不全为0首列出现0&#xff0c;且该行全为0 3.5 误差分析和计算——准3.5.1稳…

栈的顺序存储实现(C语言)(数据结构与算法)

栈的顺序存储实现通常使用数组来完成。实现方法包括定义一个固定大小的数组&#xff0c;以及一个指向栈顶的指针。当元素入栈时&#xff0c;指针加一并将元素存储在相应位置&#xff1b;当元素出栈时&#xff0c;指针减一并返回相应位置的元素。 1. 顺序栈定义 #define MaxSi…

YOLOv5-6.1源码详解之损失函数loss.py

目录 1 目标检测结果精确度的度量 2 YOLOv5-6.1损失函数 2.1 classification类别损失 2.2 confidence置信度损失 2.3 localization定位损失 3 YOLOv5-6.1损失函数loss.py代码解析 3.1 class ComputeLoss 3.1.1 __init__ 3.1.2 build_targets 3.1.3 _call__ 3.2 smo…

docker 1.13存储路径修改

由于老版本docker还没有data-root配置&#xff0c;特记录一下老版本修改配置。 新版本配置修改参考&#xff1a;https://blog.csdn.net/tootsy_you/article/details/126933702 修改步骤 编辑docker.service服务文件 vim /usr/lib/systemd/system/docker.service在EXStart添加…

leaflet:个性化配置,利用Leaflet-Geoman绘制多种图形(136)

第136个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中个性化配置,利用Leaflet-Geoman绘制多种图形。 灵活地配置Leaflet-Geoman的属性,可以产生各种美妙的绘图效果。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方…

vue下使用Echarts5绘制基础图表

项目使用Vue3加Echarts5绘制的基本图表&#xff0c;图表自适应浏览器窗口大小 先上图&#xff0c;大屏小屏都可完美展示&#xff0c;纯属练手 一 先上图 1.任意缩放窗口的大小 2.平板 3.电脑 4.饼图 5.折线图 二 后上代码 <script lang"ts"> import {d…

苹果Ios系统app应用程序开发者如何获取IPA文件签名证书时需要注意什么?

今天呢想和大家介绍介绍苹果App开发者如何获取IPA文件签名证书的步骤和注意事项。对于苹果应用程序开发者而言&#xff0c;获取IPA文件签名证书是发布应用程序至App Store的重要步骤之一。签名证书能够确保应用程序的安全性和可信度&#xff0c;并使其能够在设备上正确运行。 …

uboot 和 内存地址

前言 在使用 uboot 升级的时候&#xff0c;有个疑问&#xff1a; 通过 tftp 下载的 bin 文件&#xff0c;我该暂存在哪段内存空间&#xff1f;换句话说&#xff0c;哪段内存空间可供我存放临时数据&#xff1f; 带着这个疑问&#xff0c;开启今天的 uboot 和 内存地址 研究之旅…

【2023】COMAP美赛数模中的大型语言模型LLM和生成式人工智能工具的使用

COMAP比赛中的大型语言模型和生成式人工智能工具的使用 写在最前面GitHub Copilot工具 说明局限性 团队指南引文和引用说明人工智能使用报告 英文原版 Use of Large Language Models and Generative AI Tools in COMAP ContestslimitationsGuidance for teamsCitation and Refe…

基于SpringBoot+Vue的体育馆管理系统

基于SpringBootVue的体育馆管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 器材详情 登录界面 管理员界面 摘要 SpringBootVue的体育馆管理系统是…

【OpenCV实现图像:用OpenCV图像处理技巧之白平衡算法】

文章目录 概要加载样例图像统计数据分析White Patch Algorithm小结 概要 白平衡技术在摄影和图像处理中扮演着至关重要的角色。在不同的光照条件下&#xff0c;相机可能无法准确地捕捉到物体的真实颜色&#xff0c;导致图像呈现出暗淡、色调不自然或者褪色的效果。为了解决这个…

【经验模态分解】3.EMD模态分解算法设计与准备工作

/*** poject 经验模态分解及其衍生算法的研究及其在语音信号处理中的应用* file EMD模态分解算法设计与准备工作* author jUicE_g2R(qq:3406291309)* * language MATLAB* EDA Base on matlabR2022b* editor Obsidian&#xff08;黑曜石笔记软…

Linux安装DMETL4

Linux安装DMETL4 产品与环境介绍1 规划安装路径2 DM8安装路径2.1 达梦数据库程序安装路径2.2 初始化达梦数据库2.3 创建数据库用户名 DMETL 3 安装DMETL3.1 查看安装包与授权3.2 安装DMETL程序3.3 DMETL安装日志 4 启动DMETL5 DMETL连接数据库后会自动创建相关资源表6 达梦数据…

MySQL索引的数据结构

1. 索引及其优缺点 1.1 索引概述 MySQL官方对索引的定义为&#xff1a;索引&#xff08;Index&#xff09;是帮助MySQL高效获取数据的数据结构。 索引的本质&#xff1a;索引是数据结构。你可以简单理解为“排好序的快速查找数据结构”&#xff0c;满足特定查找算法。这些数据结…

【每日一题】咒语和药水的成功对数

文章目录 Tag题目来源解题思路方法一&#xff1a;排序二分 写在最后 Tag 【排序二分】【数组】【2023-11-10】 题目来源 2300. 咒语和药水的成功对数 解题思路 方法一&#xff1a;排序二分 我们首先对 points 进行升序排序&#xff0c;然后枚举 spells 中的 x&#xff0c;需…

IDEA 编译项目时报错:java: java.lang.OutOfMemoryError:GC overhead limit exceeded解决方法

1.问题简述 在Intellij IDEA下编译Java项目&#xff0c;报错&#xff1a;java.lang.OutOfMemoryError: …(此处忽略) GC overhead limit exceeded 2.问题分析 错误是发生在编译阶段&#xff0c;而不是运行阶段。通过查询相关资料发现&#xff0c; 1.idea编译Java项目使用的虚…

Adobe Photoshop 2020给证件照换底

1.导入图片 2.用魔法棒点击图片 3.点选择&#xff0c;反选 4.选择&#xff0c;选择并遮住 5.用画笔修饰证件照边缘 6. 7.更换要换的底的颜色 8.新建图层 9.使用快捷键altdelete键填充颜色。 10.移动图层&#xff0c;完成换底。

《开箱元宇宙》:认识香港麦当劳通过 The Sandbox McNuggets Land 的 Web3 成功经验

McNuggets Land 是 The Sandbox 于 2023 年发布的最受欢迎的体验之一。在本期的《开箱元宇宙》系列中&#xff0c;我们采访了香港麦当劳数位顾客体验暨合作伙伴资深总监 Kai Tsang&#xff0c;来了解这一成功案例背后的策略。 在不断发展的市场营销和品牌推广领域&#xff0c;不…

面试复习整理

redis持久化方式和原理 Redis持久化是指将Redis内存中的数据以某种形式保存到磁盘上&#xff0c;以保证在Redis重启后数据不会丢失。Redis支持两种持久化方式&#xff1a;RDB&#xff08;Redis DataBase&#xff09;和AOF&#xff08;Append Only File&#xff09;。 RDB持久…