如下为百度百科上的说法和视频截图:
汉诺塔(Tower of Hanoi)是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
这里用n
来表示圆盘的个数,根据规则,一次只能移一个圆盘且小盘必须在大盘之上,那么我们要移最后的第n
个圆盘,就不得不先移动n-1
个 ···,直到必须先移动第1
个圆盘,很明显的递归思想了。
由于递归思想是自身调用,这里我们可以假设n = 2
,先手动推演一下结果。
第1步:圆盘1:A -> B
第2步:圆盘2:A -> C
第3步:圆盘1:B -> C
public class HanoiTower { // 移动次数计数器 static int count = 0; public static void main(String[] args) { // 圆盘的个数 int number = 2; System.out.println("========== 移动开始,圆盘共计" + number + "个 =========="); HanoiTower.factorial(number, "A", "B", "C"); System.out.println("========== 移动结束,一共移动" + count + "次 =========="); } private static void factorial(int number, String srcTower_A, String assistTower_B, String desTower_C) { if (number == 1) { // 递归边界:将第1个圆盘从源座移动到目的座 move(number, srcTower_A, desTower_C); } else { // 将n-1个圆盘从源座移动到辅助座(n=2时,即为第1个圆盘) factorial(number - 1, srcTower_A, desTower_C, assistTower_B); // 将第n个圆盘从源座移动到目标座(n=2时,即为第2个圆盘) move(number, srcTower_A, desTower_C); // 将第n-1个圆盘从辅助座移动到目标座(n=2时,即为第1个圆盘) factorial(number - 1, assistTower_B, srcTower_A, desTower_C); } } private static void move(int diskNumber, String srcTower, String desTower) { System.out.println("圆盘" + diskNumber + ":" + srcTower + " -> " + desTower); count++; } }
从上图可以看出,已经解决了该问题,代码最迷糊的就是else
中包含的3个移动步骤了,其实如果假设i=2
的话,就很好理解了,递归嘛,自身调用一次就足够看出方案来了。而移动次数,想必你也已经看出来了,最少需要2^n - 1
次。