第一章通过三个样本问题来认识递归问题。它们:
①足够经典,被反复研究;
②都通过递归方法解决,每个问题都依赖于形式相同但规模更小的问题;
③都能够使用计算机程序实现。
目录
1 汉诺塔问题 Hanoi Tower
1.1 问题提出
有若干圆盘,从上至下直径由小到大,被一根杆A串成一座塔,此外另有两根单独的杆B和C。我们的目的在于将A上的塔移到另一根杆上。
过程当中注意:
1.1.1 一次操作在两杆之间移动一个圆盘;
1.1.2 不允许把直径大的圆盘放在直径小的圆盘上面;
1.1.3 移动方法要使得操作次数最少。
1.2 问题的递归表示
1.2.1 符号表示
我们用
T
n
T_n
Tn来表示n个圆盘从一根杆移动到另一根杆所需要的最少移动次数。显然的,
T
0
=
0
T_0=0
T0=0,
T
1
=
1
T_1=1
T1=1,
T
2
=
3
T_2=3
T2=3。
1.2.2 问题拆解(充分性证明)
接下来我们把规模为n的问题进行拆解,
要把n个圆盘从A移动到另一根杆,不妨设为B,那么我们可以分成三步进行:
①把n-1个圆盘从A移动到C,需要
T
n
−
1
T_{n-1}
Tn−1次操作;
②把最大的圆盘从A移动到B,需要一次操作;
③把n-1个圆盘从C移动到B,需要
T
n
−
1
T_{n-1}
Tn−1次操作。
这仅仅是我们移动的一种方法,并没能够证明这样做的操作次数是最小的,因此我们可以列出公式:
T n ≤ 2 T n − 1 + 1 ( n > 0 ) T_n \leq2T_{n-1}+1\ \ (n>0) Tn≤2Tn−1+1 (n>0)(公式1.1)
1.2.3 必要性证明
我们证明了
2
T
n
−
1
+
1
2T_{n-1}+1
2Tn−1+1次移动是充分的,接下来证明它是必要的。
①根据规则1.1.2,在我们移动最大圆盘的时候,其余的n-1个圆盘必然不能在目标柱上,且必然在最大圆盘所在柱子和目标柱子以外的那根柱子,否则不能移动,因此,从初始状态到可以移动最大圆盘的状态,至少需要
T
n
−
1
T_{n-1}
Tn−1次操作。
②在移动完最大盘后,将剩余n-1个盘子移到目标柱上,也至少需要
T
n
−
1
T_{n-1}
Tn−1次操作。
由此可以列出公式:
T n ≥ 2 T n − 1 + 1 ( n > 0 ) T_n \ge2T_{n-1}+1\ \ (n>0) Tn≥2Tn−1+1 (n>0)(公式1.2)
综合公式1.1和1.2,以及之前 T 0 = 0 T_0=0 T0=0的平凡解,我们可以得到
T n = { 0 ( n = 0 ) 2 T n − 1 + 1 ( n > 0 ) T_n= \begin{cases} 0\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (n=0) \\ 2T_{n-1}+1\ \ \ (n>0) \end{cases} Tn={0 (n=0)2Tn−1+1 (n>0) (公式1.3)
最终,我们得到了这样的一个递归关系。
1.3 求解递归关系
求解递归关系,就是为了不需要求解出所有小于n的问题,直接求解出大小为n的问题的答案,也称为求出递归关系的闭形式1。
除了猜测出递归关系的解,并使用数学归纳法加以证明之外,还有这样一种方法:
我们令 U n = T n + 1 U_n=T_n+1 Un=Tn+1,并结合公式1.3,我们可以得到:
U n = { 1 ( n = 0 ) 2 U n − 1 ( n > 0 ) U_n= \begin{cases} 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (n=0) \\ 2U_{n-1}\ \ \ \ \ \ \ \ \ (n>0) \end{cases} Un={1 (n=0)2Un−1 (n>0) (公式1.4)
从而求解出 U n = 2 n U_n=2^n Un=2n,从而得到 T n = 2 n − 1 T_n=2^n-1 Tn=2n−1.
1.4 汉诺塔问题的推广
to be continued
2 直线划分平面问题 Lines in the Plane
2.1 问题提出
非常的如题所示,n条直线,最多能将平面划分成几个区域的问题。
2.2 问题的递归表示
我们用 L n L_n Ln来表示n条直线最多能划分出的区域。
简单的思考可以发现,如果在一个划分被n-1条直线划分为k个区域的平面当中添加一条直线,而这第n条直线经过了k’个区域,那么它将把这k’个区域当中的每一个一分为二,因此得到k+k’个区域。
由基础的欧式几何可知,新的直线和n-1条老的直线最多有n-1个交点,且一定会有 k ≤ n k\leq n k≤n。
得到充分条件:
L n ≤ L n − 1 + n ( n > 0 ) L_n\leq L_{n-1}+n\ \ \ (n>0) Ln≤Ln−1+n (n>0) (公式2.1)
而我们只需要让每条新加入的直线不与其它任何一条直线平行,且每个交点最多只能属于两条直线,就能在上式中取等号。
观察平凡解 L 0 = 1 L_0=1 L0=1, L 1 = 2 L_1=2 L1=2,我们可以轻易看出 L n L_n Ln其实是一个等差数列求和,有:
L n = n 2 + n + 2 2 , ( n > 0 ) L_n=\frac {n^2+n+2}{2},(n>0) Ln=2n2+n+2,(n>0) (公式2.2)
我们也把首项为1,公差为1的等差数列的和 S n S_n Sn成为三角形数。
2.3 问题的推广
to be continued
3 约瑟夫环问题 Josephus Circle
闭形式,粗略地讲,是能使用与n次数无关的固定次数的标准运算求到结果的表达式。如果通过一个递归关系来求解规模是n的问题,需要把前面所有n-1个问题全都求解出来,这时运算次数很明显和n成正比,所以递归关系不是闭形式;如果通过一个或固定数量的一组表达式来求解规模为n的问题,无论n有多大,都不会影响计算次数,我们称这种表达方式为一种闭形式。熟悉算法复杂度的朋友可能已经感觉到,判断一种表达方式是否为闭形式,和判断算法时间复杂度为 O ( 1 ) O(1) O(1)还是 O ( n ) O(n) O(n)有异曲同工之处。 ↩︎