递归问题的实际运用:汉诺塔问题

简介: 递归问题的实际运用:汉诺塔问题

先来看看什么是汉诺塔问题:


来源:


相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。


5f13ddb1c7514e359ae04a7719445aa2.png



分析:对于这样一个问题,任何人都不可能直接写出移动盘子的每一步,但我们可以利用下面的方法来解决。设移动盘子数为n,为了将这n个盘子从A杆移动到C杆,可以做以下三步:


(1)以C盘为中介,从A杆将1至n-1号盘移至B杆;


(2)将A杆中剩下的第n号盘移至C杆;


(3)以A杆为中介;从B杆将1至n-1号盘移至C杆。


我们画个图示意一下:


如果只有一个盘子,那么我们直接将盘子移动C柱就行。



2ba867cf1d7248ed905d4ed7e2bc8070.png



a35270e06ebd468d9bcb9ad3b6469dcc.png

也就是A -> C 。

如果有两个盘子,我们该怎么挪呢?


f6df5cd434a34d0d8224be79015c5cd6.png

1.先将红盘移动到B柱。

A -> B



c750843b598f45bd87a90b3a726495ae.png


2.再将绿盘移到C柱。

       A -> C



20be9fc2f34b442586ca6ec6a174abb1.png


3.最后将B柱的红盘移到C柱。

       B -> C


a3f811636860452f9aab67c1229a25db.png




如果有三个盘子:

一定要保证大的在下,小的在上。


  1. A -> C



6ce615925eec4bf99bb222d6308d1b25.png


2.A ->B


1d9876882b5145f7b5ff972bf1b383be.png

3.C ->B


a3d1dfa6f3524c64826008de7101b9f4.png


4.A->C


d21a7953fa53420c9131f64a5a17834a.png

5.B -> A


d2d7b810a6c846d3a075439b296dab4c.png


6. B -> C

7. A -> C



8f952a2b02314da68a2799ec2d45d3e3.png



如果是四个柱子:


也是这种思路,我们可以把他们放到一起来对比。


1个盘子 A -> B 移动一次


2个盘子 A -> B A->C B->C 移动三次


3个盘子 A-> C A->B C->B A->C B->A B->C A->C 移动七次 公式为:2^n-1


那么如果有64个盘子我们看看需要移动多少次:


cf40ed0338e14c25a52e608e9c6ec261.png


这太大了,用我们一般的计算机来跑也需要数百年。

那么我们的代码该怎么去写呢?

public class demo {
    /**
     *
     * @param n:盘子个数
     * @param pos1:起始位置
     * @param pos2:中转位置
     * @param pos3:目的位置
     */
    public static void Hanoi(int n,char pos1,char pos2,char pos3){
        if (n == 1 ){
            move(pos1,pos3);
            return ;
        }
        //无论这个有多少个盘子,我都需要借助pos3 移动到pos2 上,只留下最底下,最大的那个盘子
        Hanoi(n-1,pos1,pos3,pos2);
        //将这个最大的盘子移动到pos3 上
        move(pos1,pos2);
        //于是问题转化成了:
        Hanoi(n-1,pos2,pos1,pos3);
        //具体是怎么操作的我们不用管
    }
    public static void move(char pos1,char pos2){
        System.out.print(pos1 + "->" + pos2 +" ");
    }
    public static void main(String[] args) {
        Hanoi(2,'A','B','C');
        System.out.println();
        Hanoi(4,'A','B','C');
        System.out.println();
    }
}

883bcba12e0a4955b8a007369694306f.png


如果这里是 64 个盘子,肯定是跑不完的。


153aca02965d4b4b8a638c345d23d1e9.png



相关文章
|
存储 分布式计算 Hadoop
元数据持久化
元数据持久化【2月更文挑战第25天】
447 1
|
存储 缓存 UED
缓存策略与Apollo:优化网络请求性能
缓存策略与Apollo:优化网络请求性能
|
机器学习/深度学习 人工智能 自然语言处理
《GraalVM:Java AI 应用性能与启动速度的优化利器》
在人工智能蓬勃发展的今天,Java 在 AI 领域占据重要地位,但也面临性能和启动速度的挑战。GraalVM 以其高效的即时编译、内存管理优化、多语言融合及提前编译等特性,显著提升了 Java AI 应用的执行效率和启动速度,助力开发者打造更高效的 AI 解决方案。通过优化类加载机制和垃圾回收,GraalVM 实现了更快的响应和更稳定的运行,适用于图像识别、智能风控、云原生服务等多种场景。
443 7
|
6月前
|
SQL 关系型数据库 MySQL
explain的type几种类型详解
在 MySQL 中,使用 EXPLAIN(或 EXPLAIN SELECT ...)可以查看 SQL 语句的执行计划,而其中最重要的字段之一就是 type。它表示 MySQL 在执行查询时访问数据表的方式(即访问类型),也叫做 连接类型(Join Type)。
|
缓存 负载均衡 监控
性能优化:Node.js高效服务器开发技巧与最佳实践
【10月更文挑战第29天】在Node.js服务器开发中,性能优化至关重要。本文介绍了几种高效开发的最佳实践,包括使用缓存策略、采用异步编程、实施负载均衡和性能监控。通过示例代码展示了如何实现这些技术,帮助开发者构建更快、更稳定的Node.js应用。
459 2
|
关系型数据库 MySQL 网络安全
DBeaver连接MySQL提示Access denied for user ‘‘@‘ip‘ (using password: YES)
“Access denied for user ''@'ip' (using password: YES)”错误通常与MySQL用户权限配置或网络设置有关。通过检查并正确配置用户名和密码、用户权限、MySQL配置文件及防火墙设置,可以有效解决此问题。希望本文能帮助您成功连接MySQL数据库。
2636 4
|
Prometheus 监控 Cloud Native
服务器监控软件
【10月更文挑战第18天】
430 1
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 IS NULL
【8月更文挑战第12天】
1097 0
在 MySQL 中使用 IS NULL
Java中的枚举类型详解:应用与最佳实践
Java中的枚举类型详解:应用与最佳实践
|
XML Java 数据库
Android App开发实战之实现微信记账本(附源码 超详细必看)
Android App开发实战之实现微信记账本(附源码 超详细必看)
863 0