这里不提供题目

汉诺塔问题是很多新手遇到的第一个难题,也许并不难,但是对于本人这种麻瓜来说第一次还是很难理解的,其中的思考过程一度让我崩溃

不过也不是不能理解的,需要比较长的时间

网络中有许多讲解视频,但是都大同小异,似乎都不是讲给麻瓜的,也可能是我们麻瓜太笨了,不过终究还是能理解的

开始吧

首先分析问题,
盘数(n)为1时,A-->C 毋庸置疑

盘数为2时,就多了两步,移走上面的小盘到B,然后大盘A-->C,最后把小盘移到C

盘数为3时,就有7步了,不过和盘数为2时的操作很相似,也是移走上面的所有小盘到B,然后大盘A-->C,最后把所有小盘移到C

注意,难理解的事来了

许多讲解会让你把多少个盘看做是两个盘,然后递归调用就行了,当时我真的是一脸雾水,这也许就是麻瓜才懂得无助感吧

我来重新理理思路,当n>2时,不难发现,当总盘数为奇数时,第一个盘都时先移动到A上,偶数是移动到B上,你可以看上面n=1,2,3的分析,你也可以自己分析n=4,5,6的情况,不过你应该不会这么闲

当柱子上的第一块盘移动到C时,第二块盘理所应当移动到B上,最后第一块盘移到B,这样就达到了第三块盘到C的条件,反之亦然

于是,我们不难看出移动多个盘子时都是先考虑 最上面的盘子 移动到 满足下面的盘子 移动到目标柱子的条件(条件就是目标柱子上没有盘(因为下面的盘子比前面移动的都大))

如果不能理解可以看看这个例子:

食堂排队打饭,有十个同学在排,后又来一个人排,如果他要排在第十位,什么条件能满足,当然就是排第一个的人打完饭走了,第二个向前一位,依次类推,排第十一位的同学就排到了第十位
这里主观做的只有一件事,就是排在第一位的同学打完饭离开了(达到了下一个同学向前的条件),后面的同学就会陆陆续续的打到饭

所以,我们要做的也是吧把前面的盘子放到满足下面的盘子移动到目标柱子的条件就可以了,唯一的区别就是要只有一个盘子时直接放,不用满足什么

函数中有语句
if(n == 1) System.out.println(A+"柱上的盘移动到"+C

当n>2时需要考虑达到满足条件,并且还要考虑上面分析的当总盘数为奇数时,第一个盘都时先移动到A上,偶数是移动到B上这个要求,我们采用递归来解决这个条件

思考一下,如何当总盘数为奇数时,第一个盘都时先移动到A上,偶数是移动到B上

想不到也没事,学会了以后就是自己看出来的了

直接展示代码

public class HannoTower{
    public static void main(String[] args){
    T tool = new T();
    tool.move(2,'一','二','三');
    }
}

class T{
    public void move(int n,char A,char B,char C){
        if(n == 1){
           
            System.out.println(n+"层"+A+"--^-->"+C);
 
        }else {
     
            move(n - 1, A, C, B);
     
            System.out.println(n+"层"+A + "-->-->" + C);
   
            move(n - 1, B, A, C);
     
        }
    }
}

不难看出,当 tool.move(2,'一','二','三');public void move(int n,char A,char B,char C)中的A,B,C会被赋值为一,二,三,
然后会跳过if语句再次调用函数,并传如参数(1, A, C, B)到下一个执行的函数中也就是说下一个函数中的A,B,C被赋值(指向)上一个函数的A,C,B
下一个函数中满足n == 1的边界条件,执行System.out.println(n+"层"+A+"--^-->"+C);
注意,重点来啦
打印A-->C是直接打印吗?
不是的,A是指向传递进来的参数A,C是指向传递进来的参数B,还没有结束,回到上一个函数中,A会指向传进来的参数B会指向传进来的参数

所以打印A--->C变成了一--->二
上图

图中的那些打印那些测试和n层是为了直观看到运行的过程,刚开始的时候我想象不出来

同理当` tool.move(3,'一','二','三');时还会执行类似的过程,递归时改变传入参数的值来改变最终打印的值

你如果理解了上面的步骤的话,我再说说这个函数中的语句的作用

if语句的就不说了

第一个move(n - 1, A, C, B);的作用是把上面的盘移动到满足下面的盘子移动到目标柱子的条件(条件就是目标柱子上没有盘(因为下面的盘子比前面移动的都大))

第二个System.out.println(n+"层"+A + "-->-->" + C);的作用就是把

中最小的盘移动到C中的作用,也是最后一步

其实为了函数的严谨还应该添加一个if语句来表示只执行n>0的情况,else要返回报错

到这里我理解的就算大致讲完了,我自己想不出来这种解决方法,能看懂,遇到类似的问题能参考解决已经是我等麻瓜的能力极限

posted on 2024-08-08 16:30  mingkangruan  阅读(13)  评论(0编辑  收藏  举报