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

news/2025/2/14 6:14:43/

目录

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]。

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


http://www.ppmy.cn/news/1207407.html

相关文章

四川思维跳动商务信息咨询有限公司可信吗?

在今天的数字化时代&#xff0c;抖音带货已成为一种全新的商业模式。许多公司都在通过这种形式进行产品推广和销售&#xff0c;其中&#xff0c;四川思维跳动商务信息咨询有限公司以其专业的服务和良好的信誉&#xff0c;在抖音带货领域赢得了广泛赞誉。 四川思维跳动商务信息…

Android Bitmap 裁剪局部

Android Bitmap 裁剪局部 在Android开发中&#xff0c;我们经常会遇到需要对图片进行裁剪的情况。裁剪图片可以提取出我们需要的局部区域&#xff0c;以满足特定的需求&#xff0c;比如头像的裁剪、图片的放大缩小等。本文将介绍如何在Android中使用Bitmap来实现图片的裁剪功能…

nodejs+vue+python+PHP+微信小程序南七街道志愿者服务平台的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Vue3全局共享数据

目录 1&#xff0c;Vuex2&#xff0c;provide & inject2&#xff0c;global state4&#xff0c;Pinia5&#xff0c;对比 1&#xff0c;Vuex vue2 的官方状态管理器&#xff0c;vue3 也是可以用的&#xff0c;需要使用 4.x 版本。 相对于 vuex3.x&#xff0c;有两个重要变…

Docker实现挂载的N种方式

目录 docker挂载实现挂载的方式绑定挂载数据卷&#xff08;Volume&#xff09;挂载DockerFile 定义数据卷临时文件系统&#xff08;tmpfs&#xff09;挂载挂载 docker挂载 默认情况下&#xff0c;在Docker容器内创建的所有文件都只能在容器内部使用。容器删除后&#xff0c;数…

已解决:云原生领域的超时挂载Bug — Kubernetes深度剖析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

ElasticSearch的文档、字段、映射和高级查询

1. 文档&#xff08;Document&#xff09; 在ES中一个文档是一个可被索引的基础信息单元&#xff0c;也就是一条数据 比如&#xff1a;你可以拥有某一个客户的文档&#xff0c;某一个产品的一个文档&#xff0c;当然&#xff0c;也可以拥有某个订单的一个文档。文档以JSON&…

浏览器添加油猴(tampermonkey)扩展

msedge浏览器为例 1.打开msedge浏览器 2.点击右上角省略号 3.点击扩展 4.点击管理扩展 5.点击获取 Microsoft Edge 扩展 6.搜索 tampermonkey 7.获取自己想要安装的油猴