汉诺塔问题

117 阅读2分钟

屏幕截图 2024-01-28 104509.png 从问题当中来看,我们可以先考虑一片到四片的情况,从之中找规律


屏幕截图 2024-01-28 104746.png

这个就不用解释了

屏幕截图 2024-01-28 104804.png

当有两块的时候,就需要用到我们的中间块来暂放了

屏幕截图 2024-01-28 104810.png 到三块的时候就会发现,第一步当中的圆盘12a->b,与两块圆盘时候a->c相似就是换的位置变了一下

接下来我们再看四块的

屏幕截图 2024-01-28 104825.png

看到这,细心的倔友就会发现第一步和最后一步和三块时候一样

面对这样的规律,我们就可以想到用递归的办法就实现它

我们可以用linkedlist的方式存储方式去存圆盘

static LinkedList<Integer>a = new LinkedList<>();
static LinkedList<Integer>b = new LinkedList<>();
static LinkedList<Integer>c= new LinkedList<>();

存入数据(圆盘)

static public void inti( int n){
    for(int i=n;i!=0;i--){
        a.addLast(i);
    }
}

我们先定义一个方法去观察每一个链表当中的元素

static public void pint(){
    System.out.println(a);
    System.out.println(b);
    System.out.println(c);
    System.out.println("-----------------");
}

接下来就是移动圆盘了,我们首先考虑一轮最后一步要干的事,就是把最下面的那个大轮盘移动到c中,这就需要我们先把上面的轮盘啊先全部移动到b中,而在n-1的时候就相当于把n时候的上层圆盘移动到c中,所以我们先要递归上层圆盘放入b,再把底层圆盘放入指定位置,再递归b中轮盘放入c当中就行了

static public void remove1(int n,LinkedList<Integer>a,
                          LinkedList<Integer>b,LinkedList<Integer>c)
{
    if(n==0){
        return;
    }
    remove1(n-1,a,c,b);
   c.addLast(a.removeLast());
   pint();
   remove1(n-1,b,a,c);
}

最后就是实现这些方法了

public static void main(String[] args) {
    inti(3);
    pint();
    remove1(3,a,b,c);

}

打开我们心爱的idea去运行看一看

[3, 2, 1] [] []

[3, 2] [] [1]

[3] [2] [1]

[3] [2, 1] []

[] [2, 1] [3]

[1] [2] [3]

[1] [] [3, 2]

[] [] [3, 2, 1]

这就是链表当中元素变化的全过程

返回题目它要求64个圆盘, 我们只需把mian中传入的n改为64就行了,但是会发现运行不完.

别去傻等,因为这运行完了,不知道要个几十年,哈哈哈

根本原因就是因为时间复杂度的问题,计算就知道是O(2^n),改进的话暂时没想好