启发
既然是非递归解法,那么运用的函数中就不能出现之间或间接地对自身的引用。迭代就是利用一个完整的解决算法,对每一步都利用该步数作为参数带入算法得出具体结果。所以要迭代,就必须分析汉诺塔移动过程中每一步体现的规律。
思路&部分代码
分解过程
每一步都可以分解为:
1.决定移动的盘号(假如对n个盘子编号,从小到大为1~n)
2.决定将盘子从哪移动到哪。
由此可知,要解决的问题就是:
1.如何确定每一步对应那个盘子;
2.如何确定盘子当前的位置和要移动的位置。
移动盘号
假设移动4个盘子,默认将盘子从1号移动到3号柱,2号柱作为临时存放点。过程如下(括号内代表移动的盘号):
1–2(1)
1–3(2)
2–3(1)
1–2(3)
3–1(1)
3–2(2)
1–2(1)
1–3(4)
2–3(1)
2–1(2)
3–1(1)
2–3(3)
1–2(1)
1–3(2)
2–3(1)
观察上面式子,可以知道:
1.总步骤数为15(也就是24 -1)
2.移动1号盘的步骤为:[1,3,5,7,9,11,13,15] ,移动2号盘的步骤为[2,6,10,14]; 移动3号盘的步骤为[4,12]; 移动4号盘的步骤为[8]
3.第一次移动1号盘在步骤1;第一次移动2号盘在步骤2;第一次移动3号盘在步骤4,第一次移动4号盘在步骤8。
间隔数
由此可看到, 1号盘的步骤数间隔为2(3-1,5-3,7-5), 2号的间隔数为4(6-2,10-6,14-10), 3号的间隔数为8(12-4).因此猜测每个盘间隔数和它的盘号有关:
盘号 | 间隔数 |
---|---|
1 | 2=21 |
2 | 4=22 |
3 | 8=23 |
4 | 24=16 |
以此类推。
证明:
递归地分析移动n个盘子的过程可得:
n=1时,移动一次;
n=2时,移动1+1+1=3次(首尾两个1分别代表移动1号的步骤);
n=3时,先移动2个盘到临时点上,再移动3号,最后把1,2号移动到终点,因此:3+1+3 = 7次.
为n时,设 a n a_{n} an为总步数,则 a n a_{n} an=2 a n − 1 + 1 a_{n-1} + 1 an−1+1
得出 a n = 2 n − 1 a_{n} = 2^{n} -1 an=2n−1
图解如下:
因此可以利用数学归纳法证明步骤间隔数和盘号的关系.
设移动总数为n的盘子们
其中1号:
因为移动了1号盘以后,下一步不可能再动1号,因此排除"存在任意连续的两步都移动1号"的假设.当移动了另外号码(假设a号)的盘子后(此时除1号呆的柱子,其他柱子上的盘子都比1号大),第三步一定会移动1号,因为移动之前a号下要么比a号大,要么没有盘子,又不可能再把a号移回去(无效操作),因此只能挪动1号.得出:一号的步骤间隔为2.
设k号盘的步骤间隔=2k 成立
k+1号:
总过程分解到(k+1)的层次,共有2(n-k-1) 个分叉.每个分叉都代表移动k个盘子的(2k-1 -1)步,因此间隔数:
a k + 1 = 2 k − 1 + 1 + 2 k − 1 + 1 = 2 k + 1 a_{k+1} = 2^{k}-1+1+2^{k}-1+1 = 2^{k+1} ak+1=2k−1+1