【递归】汉诺塔问题(Java版)

news/2024/7/20 20:17:26 标签: java, 深度优先, 开发语言

目录

1.题目解析

2.讲解算法原理

2.1.如何来解决汉诺塔问题?

2.2.为什么这道题可以用递归来做?

2.2.1 什么是递归

2.2.2 为什么会用到递归

3.如何编写递归代码?

4.递归的细节展开图


1.题目解析

汉诺塔问题链接

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

你需要原地修改栈。

示例1:

 输入:A = [2, 1, 0], B = [], C = []
 输出:C = [2, 1, 0]

示例2:

 输入:A = [1, 0], B = [], C = []
 输出:C = [1, 0]

2.讲解算法原理

2.1.如何来解决汉诺塔问题?

2.2.为什么这道题可以用递归来做?

2.2.1 什么是递归

函数自己调用自己的情况

2.2.2 为什么会用到递归
  • 在解决主问题的时候碰到相同的子问题

  • 在解决子问题的时候又碰到相同的主问题

大家发现我们的 第一个步骤和第三个步骤 全都是同样一类的问题解决 N=4 的方法和 N=3 的方法是一模一样 --> 先把除最大的盘子外的其他盘子转移到中间,后把最大盘子转到C

3.如何编写递归代码?

java">public class hanota {
    public void hanota(List<Integer> a, List<Integer> b, List<Integer> c) {
        
        dfs(a,b,c,a.size());
    }
    public void dfs(List<Integer> a, List<Integer> b, List<Integer> c,int n){
        if (n == 1){
            // 把 a 柱子的最后一个盘子移动到c
            c.add(a.remove(a.size() - 1));
            return;
        }
        // 把 a 上的 n-1 个盘子移动到b上
        dfs(a,c,b,n-1);
        // 把 a 的最上面的那个盘子放到 c 上
        c.add(a.remove(a.size() - 1));
        // 把 b 上 n-1 个盘子通过 a 放到 c 上
        dfs(b,a,c,n-1);
    }
}

在这里我曾经想过:为什么c.add这里是 a.siez() - 1 而不是a[0]

后来才明白:a[指的永远是最大的那个盘子,而 a.siez() - 1 指的是a最上面哪一个盘子

不能指定最大的那个盘子,因为在后续遍历中传入dsf的a不一定就是原a了,如果一直加a[0]会出现很多错误!!

4.递归的细节展开图


http://www.niftyadmin.cn/n/5089176.html

相关文章

python pip 安装 Crypto 不可用解决方案

简介 Crypto模块是Python中一个强大的加密模块&#xff0c;提供了许多常见的加密算法和工具。pycrypto、pycryptodome是crypto第三方库&#xff0c;pycrypto已经停止更新了&#xff0c;不建议安装这个库&#xff0c;pycryptodome是pycrypto的延伸版本&#xff0c;用法和pycrypt…

【数据结构】排序--插入排序(希尔排序)

目录 一 基本思想 二 直接插入排序 三 希尔排序 一 基本思想 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为 止&#xff0c;得到一个新的有序序列 。 实际中我们玩扑克牌时&#xff0c;就用了插入排序的思想 二…

JavaScript发布—订阅模式

JavaScript发布—订阅模式 1 什么是发布—订阅模式2 DOM 事件3 实现一个发布—订阅模式4 发布—订阅模式的通用实现5 取消订阅的事件6 全局的发布—订阅对象7 模块间通信 1 什么是发布—订阅模式 发布—订阅模式又叫观察者模式&#xff0c;它定义对象间的一种一对多的依赖关系…

springBoot 属性绑定

springBoot 属性绑定 前言可以在类中使用在方法上使用EnableConfigurationProperties 快速注册组件 前言 属性绑定是通过ConfigurationProperties(prefix “配置属性的前缀”)来实现的&#xff0c; 可以在类中使用 在方法上使用 EnableConfigurationProperties 快速注册组件 …

GB28181学习(八)——历史视音频的回放

要求 采用SIP协议实现会话&#xff1b;采用SIP扩展协议INFO方法的消息体携带视音频回放控制命令&#xff1b;采用RTP/RTCP实现媒体传输&#xff1b;媒体回放控制命令引用MANSRTSP协议中的PLAY、PAUSE、TEARDOWN的请求消息和应答消息&#xff1b;媒体流接收者可为SIP客户端、SI…

CDN到底有什么魅力,值得网站接入

当谈到提高网站性能和用户体验时&#xff0c;内容分发网络&#xff08;Content Delivery Network&#xff0c;CDN&#xff09;是一项不可忽视的技术。CDN加速已经成为许多在线企业的首选&#xff0c;用以减少加载时间、提高安全性和全球可访问性。本文将深入探讨CDN的原理、工作…

Go语言入门心法(三): 接口

Go语言入门心法(一) Go语言入门心法(二): 结构体 一&#xff1a;go语言接口认知 忙着去耍帅,后期补充完整。。。。。

CProgressCtrl进度条

CProgressCtrl 类常用成员函数 SetRange void SetRange( short nLower, short nUpper ); 为进度条控件设置范围的最小值和最大值&#xff0c;并重画进度条来反映新的范围,默认为0~100&#xff0c;若设置32位范围&#xff0c;用下面的函数。 -0x8fff~0x7FFF SetR…