分治算法解决汉诺塔问题


分治算法解决汉诺塔问题

我们将 3 个柱子分别命名为起始柱、目标柱和辅助柱。实际上,解决汉诺塔问题是有规律可循的:

  1. 当起始柱上只有 1 个圆盘时,我们可以很轻易地将它移动到目标柱上

  2. 当起始柱上有 2 个圆盘时,移动过程如下图所示:

  3. 当起始柱上有 3 个圆盘时,移动过程如图 ,仔细观察会发现,移动过程和 2 个圆盘的情况类似:先将起始柱上的 2 个圆盘移动到辅助柱上,然后将起始柱上遗留的圆盘移动到目标柱上,最后将辅助柱上的圆盘移动到目标柱上。

  1. 将起始柱上的 n-1 个圆盘移动到辅助柱上;
  2. 将起始柱上遗留的 1 个圆盘移动到目标柱上;
  3. 将辅助柱上的所有圆盘移动到目标柱上。

由此,n 个圆盘的汉诺塔问题就简化成了 n-1 个圆盘的汉诺塔问题。按照同样的思路,n-1 个圆盘的汉诺塔问题还可以继续简化,直至简化为移动 3 个甚至更少圆盘的汉诺塔问题。

 1个圆盘的次数 2的1次方减1
 2个圆盘的次数 2的2次方减1
 3个圆盘的次数 2的3次方减1
 。 。 。 。 。
 n个圆盘的次数 2的n次方减1
故:移动次数为:2^n - 1

实现代码

/**
 * @author qxL
 * @create 2021-09-22 14:47
 */
public class HanoTower {
    public static void main(String[] args) {
        move(5, 'A', 'B', 'C');
    }
    public static void move(int num, char a, char b, char c) {
        //如果只有一个盘, num ==1
        if (num == 1) {
            System.out.println("第1个盘子从 " + a + "->" + c);
        } else {
            //如果有多个盘,可以看作两个,最下面的一个,和最上面的全部
            move(num - 1, a, c, b);//把a所有的盘从a移动到b,借助c
            System.out.println("第" + num + "个盘子从" + a + "->" + c);
            move(num - 1, b, a, c);//把b所有的盘从b移动到c,借助a
        }
    }
}