汉诺塔问题(Hanoi Tower)--递归典型问题--Java版(图文详解)

news2024/11/24 16:21:57

目录

  • 概述
    • 问题来源
    • 汉诺塔问题的规则
  • 实现
    • 解题思路
      • 一个盘子
      • 两个盘子
      • 三个盘子
      • n个盘子
    • 递归
      • 概念
      • 递归特性
      • 递归的时间复杂度
      • 汉诺塔中的递归
    • 代码
  • 总结

概述

问题来源

    汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。

汉诺塔问题的规则

  1. 有三根柱子,分别记为A、B、C。开始时,所有的盘子都放在A柱子上,按照从大到小的顺序堆叠。
  2. 目标是将所有的盘子从A柱子移动到C柱子上,期间可以借助B柱子作为辅助。
  3. 在移动过程中,每次只能移动一个盘子,并且大盘子不能放在小盘子上面。
  4. 在这里插入图片描述

实现

解题思路

  1. 当只有一个盘子时,直接将盘子从A柱子移动到C柱子即可。
  2. 当有多个盘子时,可以将问题划分为三个步骤:
    • 将上面的n-1个盘子从A柱子移动到B柱子(借助C柱子);
    • 将最底下的一个盘子从A柱子移动到C柱子;
    • 将B柱子上的n-1个盘子移动到C柱子(借助A柱子)。

在这里插入图片描述
    这样问题解决了,但实际操作中,只有第二步可直接完成,而第一、三步又成为移动的新问题。以上操作的实质是把移动n个盘子的问题转化为移动n-1个盘,那一、三步如何解决?我将以1,2,3,n个盘子为例进行详细的讲解。

一个盘子

直接从A移动到C
在这里插入图片描述

两个盘子

    先把小盘先移动到B,然后把大盘移动到C,最后把小盘也移动到C
    注意:当把小盘先移动到B之后,就可以看成分别移动两个盘,那移动每个盘的时候就是移动一个盘,方法就和上面的一个盘子移动是一模一样的,ABC的位置就是相对的,这一点很重要,对于后续理解代码非常重要!!!
在这里插入图片描述
整体移动图:
在这里插入图片描述

三个盘子

先把蓝色盘子作为一个整体移动(此时宏观上看就是两个盘子的移动)
在这里插入图片描述
    橙色移动到目标柱之后,就不在思考它,先将它剔除,然后剩下的两个盘(微观),方法就和上面的两个盘子移动是一模一样的。
在这里插入图片描述

上面的过程总结一下如下图所示
    移动三个盘其实是先分成两组两个盘(第一组是宏观上,第二组是微观上,宏观微观请往上看)
接下来的两个盘又采用1个盘的挪动方法
在这里插入图片描述

n个盘子

    同理,n个盘子先把上面的n-1个盘看成一个整体先移动到B上(先不管中间是如何操作的),再把第n个盘子移动到C上,再把n-1个盘放到c上
在这里插入图片描述

    接下来把移动到C上的盘忽略掉
    剩下的就有n-1个盘子,我们把上面的n-2个盘看成一个整体先移动到A上,再把第n-1个盘子移动到C上,再把n-2个盘放到c上
在这里插入图片描述
    为了便于大家理解,我把上面两端文字放在一起,对比给大家看,着重数以里面n的变化
在这里插入图片描述
    注意:在这里,有起点柱、终点柱,和工具柱(用来中转用),这三个的位置在变换的过程中是相对的,并不是固定不变的。

递归

    从上面的分析过程来看,学过递归的同学,一定已经发现汉诺塔就是典型的递归问题
我们简单的了解一下递归

概念

    递归是一种解决问题的有效方法,在递归过程中,函数将自身作为子例程调用。
简单说程序调用自身的编程技巧叫递归。递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止。
在这里插入图片描述

递归特性

    相比其他解法,递归只需少量程序就可描述出解题过程,大大减少了程序的代码量,而且很好理解。递归的能力在于用有限的语句来定义对象的无限集合。

递归的时间复杂度

    递归复杂度 O(T) 通常是递归调用的数量(记作 R) 和计算的时间复杂度的乘积(表示为 O(s))的乘积:

O(T)=R∗O(s)

汉诺塔中的递归

    在汉诺塔问题中就是将 n 个圆盘分为 n-1 (即除最低层的圆盘)与 1 (即最底层的圆盘),将n-1个圆盘移动到中转位置,将1移动到目的位置,再将 n-1 分为 (n-1)- 1 与 1,将(n-1)- 1 移动到中转位置,将1移动到目的位置,依次类推…

代码

第一步:
把n-1个盘子 从A柱移动到B柱
把第n个盘子从A柱移动到C柱
第二步:
把n-1个盘子 从B柱移动到C柱

package algorithm.Hhanoi;

/**
 * @BelongsProject: myProject
 * @BelongsPackage: algorithm.hanoi
 * @Author:xiaonan
 * @CreateTime: 2023-07-19 09:08
 * @Description: TODO
 * @Version: 1.0
 */
public class HanoiTower {
    public static void main(String[] args) {
        int n=3;//盘子的数量
        char a='A';//A柱
        char b='B';//B柱
        char c='C';//C柱
        hanoi(n, a, b, c);
    }
    
/*第一步:
把n-1个盘子 从A柱移动到B柱
把第n个盘子从A柱移动到C柱
第二步:
把n-1个盘子 从B柱移动到C柱
注意:变的的是目标柱,终点柱和中转柱,不变的是柱号
*/
    public static void hanoi(int n,char a,char b,char c){
        if (n==1){
            System.out.println("将盘子从"+a+"移动到"+c);
        }
        else{
             将上面的n-1个盘子从A柱子移动到B柱子(借助C柱子)
            hanoi(n-1,a,c,b);
            // 将最底下的一个盘子从A柱子移动到C柱子
            System.out.println("将盘子从"+a+"移动到"+c);
            // 将B柱子上的n-1个盘子移动到C柱子(借助A柱子)
            hanoi(n-1,b,a,c);
        }
    }
}

    运行上述代码,可以得到输出结果(这表示将3层汉诺塔从柱子A移动到柱子C需要的步骤):
在这里插入图片描述

    在上述代码中,hanoi函数是递归函数,它实现了汉诺塔问题的解决方案。在每一次递归调用中,问题规模都减小了1,直到问题规模为1时,递归终止。
在这里插入图片描述

总结

    汉诺塔问题实质是把移动n个盘子的问题转化为移动n-1个盘,依据该原理,层层递推,即可将原问题转化为解决移动n -2、n -3… … 3、2,直到移动1个盘的操作,而移动一个盘的操作是可以直接完成的。至此任务真正完成了。而这种由繁化简,用简单的问题和已知的操作运算来解决复杂问题的方法,就是递归法,汉诺塔问题是用递归方法求解的一个典型问题。
    如果大家还有什么问题,欢迎给我留言,我们一起讨论,非常感谢大家的阅读,如果觉得我的文章不错,请点赞收藏哦~

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

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

相关文章

2023无监督摘要顶会论文合集

2023无监督摘要顶会论文合集 写在最前面ACL-2023Aspect-aware Unsupervised Extractive Opinion Summarization 面向的无监督意见摘要(没找到)Unsupervised Extractive Summarization of Emotion Triggers *情绪触发(原因)的 *无监督 *抽取式 摘要&#…

Python Request get post 代理 基本使用

Python Request get post 代理 常用示例 文章目录 Python Request get post 代理 常用示例一、Pip install requests二、Requests 请求时携带的常用参数1、参数说明2、headers3、requests 常用参数:url、headers、proxies、verify、timeout 三、Requests Get Post1、Get2、Post…

【Kotlin】基础速览(1):操作符 | 内建类型 | 类型转换 | 字符串模板 | 可变 var 和不可变 val

📜 本章目录: 0x00 操作符(operators) 0x01 内建类型(Build-in) 0x02 类型转换:显式类型转换 0x03 在较长数字中使用下划线 0x04 字符串(String) 0x05 字符串模板&…

grpc中间件之链路追踪(otel+jaeger)

参考文档 https://github.com/grpc-ecosystem/go-grpc-middleware/blob/main/examples/client/main.go https://github.com/grpc-ecosystem/go-grpc-middleware/blob/main/examples/server/main.go https://github.com/open-telemetry/opentelemetry-go/blob/main/example/jaeg…

基于深度学习的高精度道路瑕疵检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要:基于深度学习的高精度道路瑕疵(裂纹(Crack)、检查井(Manhole)、网(Net)、裂纹块(Patch-Crack)、网块(Patch-Net)、坑洼块&#x…

销售易的12年与七个瞬间

导读:企业级没有捷径 12年对一家企业意味着什么? 在消费互联网领域,12年足够长,短短几年内上市的故事过去屡见不鲜。在企业服务的toB领域,产业成熟和企业发展的时间维度被拉长,但故事同样精彩。 2023年7月1…

漫谈大数据时代的个人信息安全(三)——“点赞之交”

大数据时代的个人信息安全系列三:“点赞之交” 1. 点赞之交2. 点赞诈骗3. 个人信息保护小贴士 互联网就像公路,用户使用它,就会留下脚印。 每个人都在无时不刻的产生数据,在消费数据的同时,也在被数据消费。 近日&am…

传智教育成功入选教育部2023年产学合作协同育人项目

传智教育成功入选教育部2023年产学合作协同育人项目 近日,教育部产学合作协同育人项目专家组发布《关于公布教育部产学合作协同育人项目指南通过企业名单(2023年5月)的通知》,传智教育申报的“教学内容和课程体系改革项目 、师资…

zygote forkSystemServer及systemServer启动

###zygote forkSystemServer方法 通过上一篇文章我们了解到zygote 在ZygoteInit.java类的main方法中调用forkSystemServer方法 UnsupportedAppUsagepublic static void main(String[] argv) {ZygoteServer zygoteServer null;....省略部分代码//根据环境变量(LocalServerSocke…

向量检索增强chatglm生成

背景: 基于chatglm构建agnet:chatglm实现Agent控制 - 知乎 前面一篇文章已经介绍了如何去搭建LLM Agent控制系统,也简单介绍了如何去构建Toolset和构建Action。但是在上篇文章中Toolset其实是基于搜索api构建的,从这篇文章开始后…

C++ stack和queue 模拟实现

stack和queue 模拟实现 模拟栈实现模拟队实现 模拟栈实现 1 栈是一种容器适配器,专门设计用于后进先出的后进先出环境,在这种环境中,元素只从容器的一端插入和提取。 2 栈是作为容器适配器实现的,这些适配器是使用特定容器类的封装…

获取gitlab上项目最近更新时间

获取gitlab上项目列表过程及脚本_xiaodaiwang的博客-CSDN博客使用Python及shell,获取gitlab上项目列表过程及脚本https://blog.csdn.net/xiaodaiwang/article/details/131781316?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rI…

【字符串编码解码问题】

字符串中编码解码问题 1.编码 byte[] getBytes():使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到…

Minecraft 1.20.x Forge模组开发 02.物品栏+方块+物品

我们本次在1.20中添加一个属于自己模组的物品栏、物品和方块。 效果演示 效果演示 效果演示 1.在项目中新建一个int包,用于存放所有注册类,在init包中新建ItemTabInit类: ItemTabInit.java package com.joy187.re8joymod.init

【半监督医学图像分割 2023 CVPR】PatchCL

文章目录 【半监督医学图像分割 2023 CVPR】PatchCL摘要1. 简介2. 相关工作2.1 半监督学习2.2 对比学习 3. 方法3.1 类感知补丁采样3.2 伪标记引导对比损失3.3 总体学习目标3.4 伪标号生成与求精 4. 实验5. 结果 【半监督医学图像分割 2023 CVPR】PatchCL 论文题目:…

行为型模式 - 模板方法模式

概述 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。 例如&#…

JAVA ---- 经典排序算法

目录 一. 插入排序 1. 直接插入排序 代码演示 2.希尔排序( 缩小增量排序 ) 二. 选择排序 1.直接选择排序 代码: 2. 堆排序 代码 三. 交换排序 1. 冒泡排序 代码 2. 快速排序 代码(有注释): 动图来自网…

Mysql教程(四):DML学习

Mysql教程(四):DML学习 前言 DML-介绍 DML英文全称是Data Manipulation Language数据库操作语言,用来对数据库中表的数据记录进行增删改查。 添加数据(INSERT)修改数据(UPDATE)删除…

Java 串口通讯 Demo

为什么写这篇文章 之前职业生涯中遇到的都是通过tcp协议与其他设备进行通讯,而这个是通过串口与其他设备进行通讯,意识到这里是承重板的连接,但实际上比如拉力、压力等模拟信号转换成数字信号的设备应该是有相当一大部分是通过这种方式通讯的…

为你精选5款体验极佳的原型设计工具!

在绘制原型图的过程中,使用一款的简单易操作的原型设计工具是非常重要的,本文精选了5款好用的原型工具与大家分享,一起来看看吧! 1、即时设计 即时设计是国内很多设计师都在用的原型设计工具,同时它也是国产的原型设…