汉诺塔代码如下:
public static void main(String[] args) {
hanoiTower(3, 'A', 'B', 'C');
}
public static void hanoiTower(int num, char start, char mid, char end) {
//如果只有一个盘
if (num == 1) {
System.out.println("第1个盘从 " + start + "->" + end);
} else {
//如果我们有 n >= 2 情况,我们总是可以看做是两个盘 1.最下边的一个盘 2. 上面的所有盘
//1. 先把 最上面的所有盘 A->B, 移动过程会使用到 c
hanoiTower(num - 1, start, end, mid);
//2. 把最下边的盘 A->C
System.out.println("第" + num + "个盘从 " + start + "->" + end);
//3. 把B塔的所有盘 从 B->C , 移动过程使用到 a塔
hanoiTower(num - 1, mid, start, end);
}
}
为了便于理解,试着让num传入3,汉诺塔最难理解的部分在于分治的搬运细节。debug一遍后得到:
注:以下三步递归从进递归到出递归 保持start =A,mid=B,end =C。
1)刚进入 hanoiTower(num - 1, start, end, mid);时 num=3 , num-1=2 , start = A , mid=B ,end = C.
进入递归首先要明确这次递归的目的,经过debug 出hanoiTower(num - 1, start, end, mid);时结果如下:
第1个盘从 A->C
第2个盘从 A->B
第1个盘从 C->B
这也正符合此函数传参设置位置的含义 :
搬运盘数num-1为2,从A点出发,借助C点到达B点。
最终效果也是A点最上面的两个盘去了B点。
2)然后是 System.out.println(“第” + num + "个盘从 " + start + “->” + end); 也就是输出 num=3
第3个盘从A ->C
3)最后进入 hanoiTower(num - 1, mid, start, end); 此时num=3 ,num-1=2 , mid= B , start = A , end =C
此条语句执行完得到:
第1个盘从 B->A
第2个盘从 B->C
第1个盘从 A->C
这也正符合此函数传参设置位置的含义 :
搬运盘数num-1为2,从B点出发,借助A点到达C点。
最终效果也是B点最上面的两个盘去了C点。
延申一下:那么,如果我们把num 设置为如4,5 ,10…等等其他参数,经过递归,每一步也是同num=3一样 参数体现过程。且经过测试分治法求解问题与动态规划算法不同的地方在于,其子问题之间相互独立,各个子阶段的求解互不干涉,每次子阶段求解都可以视为是重新开始计算。
如num=4,num-1=3,其第一步 从A点搬运三个去B点 (等于执行hanoiTower(num=3,start=A,mid = C,end =B),执行这条语句 还要再进入新递归),第二步第4个盘子从A点到C点 , 第三步从B点把三个盘子从B点搬运到C点(等于执行hanoiTower(num=3,start=B,mid = A,end =C))。
总结一下:分而治之, 递归汉诺塔体现了分治思想,参数设置体现出了执行过程,解决了一个个小过程 把小过程的效果结合起来就是正确结果。