Java用递归方法解决汉诺塔问题详解
作者:Killing?Vibe 发布时间:2022-11-23 03:11:40
前言
博主之前有写过关于递归问题的思维模式:
递归的思路
下面将用这种思维模式来求解经典汉诺塔问题。
一、问题描述
汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
问应该如何操作?
玩法如下:
1.有三根杆子A,B,C。A杆上有若干碟子
2.每次移动一块碟子,小的只能叠在大的上面
3.把所有碟子从A杆全部移到C杆上
二、问题分析
(两步直接解决问题)
1.第一步(先思考终止条件)
考虑n=1的情况:
只需要把这个块从A移到C即可。
2.第二步(宏观看待整个问题)
当n>=2时,把如图蓝色框框想象成上面的n-1个块(我把它称为一堆块),红色框框表示的是最下面的一块(命名为底块),这样问题可以简化为如图所示的三步。
第一步:先把上面的一堆块 从A(起始柱子)移动到B(目标柱子)上,在这个过程中,C(辅助柱子)起到中转的作用(因为题目要求移动的过程中,小盘子要保证在大盘子上面)
第二步:把最下面的红色大块直接从A(起始柱子)移动到C(目标柱子)。这里注意,这一步的目标柱子和第一步的不一样。
第三步:把上面的一堆块从B(起始柱子)移动到C(目标柱子)上,A(辅助柱子)起到中转的作用。
三、解决方案
那么问题就很简单了,递归的代码就分为两部分:终止条件和递归逻辑。
上一篇博客讲到,我们思考递归问题的时候,可以直接把这个大问题拆解成很多个子问题,想象这个功能别人已经写好了(就是这个递归函数),我们做不到的功能直接调用这个递归函数就可以(注意逻辑)。
public class Recursion {
public static void main(String[] args) {
int n = 3;
hanoiTower(n,'A','B','C');
}
/**
* 传入n个盘子,编号从1..n,我就能按照汉诺塔的规则,从目标盘子A -> C ,B是辅助盘
* @param nDisks
* @param A 起始柱子
* @param B 辅助柱子
* @param C 目标柱子
*/
public static void hanoiTower(int nDisks,char A,char B,char C) {
// 边界
if (nDisks == 1) {
// 直接一步到位,用不到B,A上的这一个盘子从A -> C
move(nDisks,A,C);
return;
}
// n >= 2,核心步骤1,先把顶上的 n -1个小盘子从A -> B,C作为辅助
hanoiTower(nDisks - 1,A,C,B);
// 核心步骤2.此时A上就剩下第n个盘子,一步到位将最大的这个盘子一次移动到C
move(nDisks,A,C);
// 核心步骤3.此时再把B上的这n-1个盘子从B -> C,A作为辅助
hanoiTower(nDisks - 1,B,A,C);
}
/**
* 将编号为n的盘子从sourceTower移动到destTower
* @param nDisks
* @param sourceTower
* @param destTower
*/
public static void move(int nDisks, char sourceTower, char destTower) {
System.out.println("编号为"+nDisks+"的盘子正在从"+sourceTower+"->"+destTower);
}
四、示例
n=3的时候
来源:https://blog.csdn.net/qq_43575801/article/details/124135450


猜你喜欢
- 本文实例讲述了C#实现的xml操作类,分享给大家供大家参考,具体如下:using System;using System.Data;usin
- import java.util.Scanner;public class VariableExchange { &n
- 本文实例为大家分享了java使用HashMap实现斗地主的具体代码,供大家参考,具体内容如下案例介绍按照斗地主的规则,完成洗牌发牌的动作。
- 很早以前为了快速达到效果,使用轮询实现了在线聊天功能,后来无意接触了socket,关于socket我的理解是进程间通信,首先要有服务器跟客户
- 自定义控件在android中无处不见,自定义控件给了我们很大的方便。比如说,一个视图为imageview ,imagebutton ,tex
- 前言Android 很多场合需要使用到数据加密,比如:本地登录密码加密,网络传输数据加密,等。在android 中一般的加密方式有如下:亦或
- Spring或SpringBoot开启事务以后无法返回自增主键场景:保存订单和订单详情,订单详情需要订单id,数据库中的订单表是自增主键,开
- 详解JDK中ExecutorService与Callable和Future对线程的支持1、代码背景: 假
- BottomBarBottomBar是Github上的一个开源框架,因为从1.3.3开始不支持fragments了,要自己配置,弄了很久,不
- 前言近期有个业务需求,涉及用户付费相关的计算,需要一个日历组件,组件功能如下:仅支持从明天开始选择预定日期仅支持可选范围内的日期日期的选择是
- 前言我身边有一部分开发的小伙伴,存在着这样一种习惯。某一天,突然看到某一款 App 上有个很漂亮的自定义控件(动画)效果,就会绞尽脑子想办法
- 本文实例为大家分享了Android仿美团下拉菜单的实现代码,分类进行选择,供大家参考,具体内容如下效果图操作平台AS2.0第三方框架:but
- 这篇文章主要介绍了Java List分页功能实现代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- 1. IOC和DI首先,我们应该明确,IOC是一种思想,并不是Spring特有的,而是软件工程逐步发展的一种产物,是一种优秀的编程思想,之所
- 前言我们书接上文,我们在了解LINQ下面有说到在本地查询IEnumerbale主要是用委托来作为传参,而解析型查询IQueryable则用E
- 通过本文你可以用非常简短的代码替代业务逻辑中的判null校验,并且很容易的在出现空指针的时候进行打日志或其他操作。注:如果对Java8新特性
- * 的实现使用的模式:代理模式。代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。类似租房的中介。两种 * :(1)jd
- 1、迭代器迭代器(iterator)解决的是集合访问的问题,提供一种方法顺序访问一个集合对象中的各个元素,而不暴露对象内部标识。迭代器还有一
- Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都会有各自的用途,以及创建和销毁的时间,有的区
- Map接口简介Map接口是一种双列集合,它的每个元素都包含一个键对象Key和值对象Value,键和值对象之间存在一种对应关系,称为映射。从M