汉诺塔
hanoi塔问题是法国数学家卢卡斯发明的问题,简单的说就是给你三根柱子,其中初始阶段所有的n个盘子都按照从大到小放置到一条柱子上。
现在的问题是:如何移动盘子可以使用最少的步骤把所有的盘子移动到另一个柱子上?在任意时刻,大盘子都在小盘子的下面。
首先我们可以从最简单的情况入手,即n=3时:
这里我们编一下号方便叙述
下面具体分析一下
步骤1:此时 A 柱为源柱,B 柱为目标柱,C 柱为辅助柱,将1,2,即n - 1个圆盘移到了B柱上,C柱为空,A柱还剩下一个最大的盘子。
将编号为1的盘子从A -> C
将编号为2的盘子从A -> B
将编号为1的盘子从C -> B
步骤2:将最大的盘子移动到了目标柱C上
将编号为3的盘子从A -> C
步骤3: A为辅助,C为目标,将B柱上的n - 1个盘子通过A最终移动到 C 柱上。
将编号为1的盘子从B -> A
将编号为2的盘子从B -> C
将编号为1的盘子从A -> C
所以当n=3时,问题就解决了,需要7步
那么我们推广到一般形式
假如有 n 个盘子
我们要将这 n 个盘子移到第三个柱子上,先需将前 n-1 个盘子移到第二个柱子上,再将第 n 个盘子移到第三个柱子上,最后将这 n 个盘子移到第三个柱子上。
要将这 n-1 个盘子移到第三个柱子上,先需将前 n-2 个盘子移到第二个柱子上,再将第 n-1 个盘子移到第三个柱子上,最后将这 n-1 个盘子移到第三个柱子上。
以此类推
需要将前n-1的所有盘子先移到第二个柱子上,再移动到第三个柱子上
也就是说,再有n个盘子时,需要将前n-1的所有盘子移动两次
F
(
n
)
=
2
∗
F
(
n
−
1
)
+
1
F(n)=2*F(n-1)+1
F(n)=2∗F(n−1)+1
两遍同时加1
F
(
n
)
+
1
=
2
(
F
(
n
−
1
)
+
1
)
F(n)+1=2(F(n-1)+1)
F(n)+1=2(F(n−1)+1)
F
(
n
)
+
1
=
2
n
F(n)+1=2^n
F(n)+1=2n
F
(
n
)
=
2
n
−
1
F(n)=2^n-1
F(n)=2n−1
不难看出,汉诺塔的问题本身是一个大问题,我们可以将这个大问题转化为许多个相似的小问题来进行解决,这就是递归的思想
那么从上面的分析过程可以看出:
递归的本质:把大规模的问题转换为小规模问题进行求解,自顶向下。
递推的解决:自底向上,从小的问题开始向上求解规模大的问题。
共同的特点:问题的求解具有状态可转移的特性,即问题的求解并不是绝对独立的。
那么下面给出一道同样运用递归解决的例题
平面直线问题
这个问题很简单:平面上n条直线最多能够将平面划分为多少个区域?
对于这个问题,我们还是先研究小的情形。我们规定对于n nn条直线来说,该问题的最优解为Tn
n=0:显然区域的数量为T0=1
n=1:显然区域的数量最多为T1=2
n=2:两条直线相交,最多可以得到区域数量T2=4
n=3:三条直线两两相交,手动推导一下,显然最多的区域数为T3=7
现在我们来研究直线数为n的问题的解,从上面的小的情形可以知道,问题的解决思路就是:每一次加上的线都尽量去与所有已有的直线相交,这样可以切割更多的区域,对于问题规模为n的时候而言,当且仅当第n条直线与已有的n−1条直线相交时,可以切割出多的n个区域。那么可以得到:
T
n
=
T
n
−
1
+
n
T_n=T_{n-1}+n
Tn=Tn−1+n
至此,该问题已经得到了解答,可以发现解题的思路和汉诺塔的问题思路一模一样,都是基于递归式求解。
总结
通过以上两道题目分析,我们可以总结出数列中递归方法的关键:
找出大规模问题与小规模问题的关系,这样通过递归使问题的规模逐渐变小。也就是找出数学里的递归公式,后一项与前项的关系
最后,给出一个练习题目:
约瑟夫问题(THE JOSEPHUS PROBLEM)
这个问题非常巧妙,相传是在一个洞穴内,数十名反抗者不想被敌人杀死,决定自杀的故事。所有的人都围坐成一个圆圈,每隔一个人就自杀一次,约瑟夫不想死,他一下子就找到了幸存者的位置。
这里给出最后的结果:
对于人数为偶数的情况,有递归式:
T
2
n
=
2
∗
T
n
−
1
T_{2n}=2*T_n-1
T2n=2∗Tn−1
对于人数为奇数的情况,有递归式:
T
2
n
+
1
=
2
∗
T
n
+
1
T_{2n+1}=2*T_n+1
T2n+1=2∗Tn+1
大家可以自行探究