首页 > 其他分享 >征服汉诺塔问题

征服汉诺塔问题

时间:2023-03-18 18:45:03浏览次数:40  
标签:移动 target Move 征服 问题 source 汉诺塔 盘子 disk

1.递归

汉诺塔问题

很多人都听说过汉诺塔问题,这是来源于印度的古代游戏。一个板子上有三根柱子以及一些大小和颜色各不相同的圆盘。我们分别把这三根柱子叫做起始柱A、辅助柱B已经目标柱C,游戏的要求如下:

把起始柱A上所有的圆盘都移动到C柱,且在移动过程中始终保持圆盘从小到大排列,即大盘在下、小盘在上。

移动过程中可以把盘子放在A、B、C任意一杆上。

场景如图所示:

由于盘子的数量是不固定,数量越大,越难直接分析出每个步骤。所以需要把问题简化到我们可以分析的程度,然后找到算法来解决。如果存在某种规律,那么可以考虑用递归来解决问题了。

从最简单的情况开始分析,如果圆盘数量只有1个,那么步骤非常简单:

把圆盘从A柱移动到C柱。过程如图所示。

如果是2个盘子,那么需要三步:

1.先把最上面的小盘子从A移动到辅助柱B,

2.然后把最大的盘子从A移动到C。

3.然后把最小的盘子从B移动到C。

如图所示,一共三步。

到目前为止没发现什么规律,需要进行增加盘子。

当盘子数量变成3,则步骤变多了。经过实验,如下:

1.把盘子从A移动C。

2.把盘子从A移到B。

3.把盘子从C移到B。

4.把盘子从A移动到C。

5.把盘子从B移动到A。

6.把盘子从B移动到C。

7.把盘子从A移动到C。

发现了一些规律,假设一共要转移N个盘子(N大于0,且为正整数):

  1. 每次都是先把除了最后一个盘子之外的盘子,也就是N -1个盘子先从起始柱A移动到了辅助柱B。
  2. 然后把最后一个盘子直接从起始柱A移动到目标柱C。
  3. 把N-1个盘子从辅助柱B移动到目标柱C。

通过重复将问题分解为同类的子问题而解决问题的方法,我们找到了递归终止的条件,就是当N等于1。

于是可以开始写代码了,JS实现如下所示:

/**
 * The solution of the hanoi question
 * 
 * @param {number} num  the number of the disks
 * @param {string} source  start bar name
 * @param {string} buffer  auxiliary bar name
 * @param {string} target  target bar name
 * @returns 
 */
function hanoi(num, source, buffer, target) {
    // When the num is 1, we can move the disk from source to target directly
    if (num === 1) {
        console.log(`Move the disk from ${source} to ${target}`);
        return;
    }

    // move source to buffer
    hanoi(num - 1, source, target, buffer);
    // move 1 from source to target
    hanoi(1, source, buffer, target);
    // move num - 1 from buffer to target
    hanoi(num - 1, buffer, source, target);
}

测试一下三个盘子的情况,结果输出如下:

Move the disk from A to C
Move the disk from A to B
Move the disk from C to B
Move the disk from A to C
Move the disk from B to A
Move the disk from B to C
Move the disk from A to C

对于递归问题,最终要的是找到递归终止条件和递推函数,也要注意有时候递归深度太大,会导致性能问题。征服汉诺塔问题,我们也同时弄懂了如何用好递归。

标签:移动,target,Move,征服,问题,source,汉诺塔,盘子,disk
From: https://www.cnblogs.com/freephp/p/17231465.html

相关文章

  • 动态规划之背包问题
    背包问题1.01背包问题有N件物品和一个容量是V的背包。每件物品只能使用一次。第i件物品的体积是\(v_i\),价值是\(w_i\)。求解将哪些物品装入背包,可使这些物品的总体......
  • #yyds干货盘点 【React工作记录二十四】ant design form赋值问题
     目录​​前言​​​​导语​​​​解决思路​​​​总结​​前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五......
  • java.sql.SQLSyntaxErrorException: Table 'test.user' doesn't exist报错问题解决
    以下内容仅供自己学习使用,侵权必删在使用mubatis-plus的时候报错了以下内容java.sql.SQLSyntaxErrorException:Table'test.user'doesn'texist解决方法:2.1在......
  • 插件化架构设计(2):插件化从设计到实践该考量的问题汇总
    根据《插件式可扩展架构设计心得》精读扩展版怎么实现插件化模式插件模式本质是一种设计思想,并没有一个一成不变或者是万金油的实现。但我们经过长期的代码实践,其实已经......
  • 项目管理的问题
    目标管理时间管理进度管理资源管理质量管理沟通管理:我的诉求,对方的问题,一起解决问题。风险管理:推动团队放入合适的资源在疑难点以及突发问题制度管理采购管理绩......
  • 插件化架构设计(1):插件化架构能解决什么问题?为啥选它?
    前面是概念内容,在实现的时候,google搜的资料进行汇总所做的笔记,看具体事件,从标题“插件实践方案” 开始看如何解决代码重用、快速开发随着MVVM的框架和库的流行,想必组......
  • 安全性、活跃性以及性能问题
    安全性并发bug三大源头源头原子性问题可见性问题有序性问题bug风险点存在共享数据并且该数据会发生变化(即多个线程会同时读写同一数据)分类数据竞争当多个线......
  • redis常见问题总结
    redis主从是异步模式AOF和RDB复制都是才有子进程共享内存,写时复制实现的。Redis为了避免AOF文件越写越大,提供了AOF重写机制,当AOF文件的大小超过所设定的阈值后,Re......
  • Vue3跨域问题Access to XMLHttpRequest at ‘http://127.0.0.1:8000/login‘ from ori
    这一个bug折磨了我一下午,终于解决了首先解决跨域问题需要修改vue.config.js文件在vue.config.js中添加devServer:{proxy:{'/api':{target:......
  • arthas排查线上问题真是太好用了!
    先贴帮助地址 https://arthas.aliyun.com/doc/jfr.html 最近发现的线上问题排查神器,其实也知道大半年了,最近才开始正式使用。也算是多了个定位问题的手段了。......