汉诺塔递归问题,递归思路详解

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

f37ac26b3fd3471192ba533664a11bdd.png

 如果只有一个盘子,那么移动的步骤就是将 a上的一个盘子挪到 C,
        记作 A  ->  C 
46cf1a98870241d79259d72257651d00.png

 

如果有两个盘子,则先把A上的一个盘子挪到B,然后将A上的最大的盘子挪到C,最后把B上的盘子挪到C,记作
        A->B
        A->C
        B->C
29cf461c04a1484aac51156c9ea2d929.png
如果有三个盘子,重复上面的步骤,可以得到:
        A->C
        A->B
        C->B
        A->C
        B->A
        B->C
        A->C 

 

那么如果有n个盘子呢?如何将A上的n个盘子挪到C上?

一步一步拆解比较难,不妨将A上的上面 n-1 个盘子看做一个整体,并将其从A上挪到B上,然后将A上的最大的盘子从A上挪到C上,那么问题就变成了,如何将B上的 n-1 个盘子从B上挪到C上。如图
e9f3b06f78194609a0ffccfc3e691fe1.png

 514e4560638147238dc0bf9448e1a92c.png

 如何构建n和n-1之间的关系?

如果这样还看不出来的话,把图换个位置再看看:

1fc36ef312c14fb292f4b7dc5d41ca76.png

 可以发现,其实A上没有盘子,C上有一个最大的盘子,可以盛放所有的大小的盘子,相当于没有盘子,这个时候问题就是如何将B上n-1 个盘子挪到C上,那么这个问题就又回到了第一步中的:

如何将A上的n个盘子挪到C上:如下图
500d27fd0cb840f091385da010744bd8.png

 所以接下来就是将B上的n-2个盘子,挪到A上,然后将B上最大的盘子挪到C,最后将A上的n-2个盘子全部挪到C,问题就变成了如何将n-2个盘子如何从A上挪到C,这个时候又需要将借助B。先将A上的n-3个盘子挪到B,然后将A上最大的盘子挪到C......... 

 

可以看出来汉诺塔的递归思路就出来了,他就是不断地借助A柱子和B柱子,将单个盘子,逐个挪到C盘子。

下面是我画的图解
7b52f56377c5489481e44d86f7a9733d.png

 完整代码: java↓↓↓

public class Test {
        public static void hannota(int n,char A,char B,char C) {
            if(n == 1){
                move(A,C);
                return;
            }
            hannota(n-1,A,C,B); // 将n-1个盘子从A经过C挪到B上
            move(A,C);        // 将 A上的盘子挪到C上
            hannota(n-1,B,A,C);  // 再将n - 1 个盘子从B经过A挪到C上
        }
    
    public static void move(char a,char b){
        System.out.print(a+"->"+b+" ");
    }
    public static void main(String[] args) {
        hannota(1,'A','B','C'); // 测试一个盘子
        System.out.println();
        hannota(2,'A','B','C');  // 测试两个盘子
        System.out.println();
        hannota(3,'A','B','C');  // 测试三个盘子
    }
}

python版本↓↓↓

def hannota(n, A, B, C): #将 A柱子上的N个盘子经过B挪到
    if n == 1:           # C上
        move(A, C)
        return
    else:
        hannota(n - 1, A, C, B) #将N-1个盘子从A经过B挪到
        # C上,和我们上面的图一一对应
        move(A, C)           # 打印这一步
        hannota(n - 1, B, C, A) # 继续,将n-1个盘子从B经过A
def move(pos1, pos2):             # 挪到C上。
    print(pos1, ' -> ', pos2, sep='')

hannota(5, 'A', 'B', 'C')

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值