问题定义:给定一个由 \(n\) 个圆盘组成的塔,这些圆盘按照大小递减的方式套在三根桩柱中的一根上。我们的目的是要将整个塔移动到另一根桩柱上,每次只能移动一个圆盘,且较大的圆盘在移动过程中不能放置在较小的圆盘上面。记最少移动次数为 \(T_n\)。
那么我们如何找出汉诺塔问题的递推式呢?书中给出的做法是从问题中寻找递归的过程,然后结合上下界来得出递推关系。
首先,将 \(n-1\) 个小的圆盘经过 \(T_{n-1}\) 次操作可以从原始桩柱移动到另一个桩柱上。然后,移动最大的圆盘到目的桩柱上,花费一次操作。最后,将 \(n-1\) 个小的圆盘经过 \(T_{n-1}\) 次操作移动到目的桩柱上。这样,至多 \(2T_{n-1}+1\) 次操作就可以移动 \(n\) 个圆盘了,我们就得到总移动次数 \(T_n\) 的上界
\[T_n \leq 2T_{n-1} + 1, n > 0.
\]
那么是否有少于 \(2T_{n-1}+1\) 次移动的操作呢?实际上是没有的。最大的圆盘必须要进行移动,此时上面的 \(n-1\) 个小的圆盘必须处于其他的桩柱上,这需要 \(T_{n-1}\) 次操作。而后将 \(n-1\) 个小的圆盘移动到最大的圆盘上,也需要 \(T_{n-1}\) 次操作。因此,至少需要 \(2T_{n-1}+1\) 次操作来移动 \(n\) 个圆盘,我们就得到总移动次数 \(T_n\) 的下界
\[T_n \geq 2T_{n-1} + 1, n > 0.
\]
结合上下界和初值,我们得到 \(T_n\) 的递推关系
\[\begin{align*}
T_0 &= 0; \\
T_n &= 2T_{n-1} + 1, n > 0.
\end{align*}
\]
上面等式给出的解是递归形式,我们需要求出其封闭形式(也称一般表达式)。
封闭形式求解
最常用的封闭形式求解方法是,首先列出解的前几项,从数据中寻找规律,然后猜测可能的解的表达式,最后使用数学归纳法进行证明。其他常用的方法还有,借助等差/等比数列求解、使用特征方程求解、使用生成函数求解、直接展开等。
数学归纳法证明
我们先列出递推式的前几项
\[\begin{align*}
T_3&=2\times3+1=7, \\
T_4&=2\times7+1=15, \\
T_5&=2\times15+1=31.
\end{align*}
\]
观察以上规律,我们可以猜测这个递推关系的解是
\[T_n=2^n-1, n\geq0.
\]
下面我们使用数学归纳法进行证明:
- 将 \(n=0\) 带入等式,\(T_0=2^0-1=0\),符合初值;
- 假设 \(n=k-1\) 时命题成立;
- 当 \(n=k\) 时,$ T_k = 2T_{k-1}+1 = 2(2^{k-1}-1)+1 = 2^k-1 $,命题成立。
等比数列求解
根据递推关系,我们可以构造公式
\[T_n+1=2(T_{n-1}+1).
\]
这是等比数列的形式,可以得到等比数列通项公式
\[T_n+1=2^{n-1}(T_1+1)=2^n.
\]
则
\[T_n=2^n-1.
\]
特征方程求解
题目给出的是非齐次的递归关系,我们先考虑齐次递归关系
\[T_n = 2T_{n-1}.
\]
它的特征方程是
\[x-2=0.
\]
方程只有一个特征根 \(q=2\),从而得到方程的通解
\[T_n = c2^n.
\]
现在我们求非齐次递归关系的特解。根据递归关系的非齐次项,我们假设其特解是
\[T_n = r.
\]
带入递推关系有
\[r = 2r + 1.
\]
得到
\[r = -1.
\]
非齐次递归关系的解,为齐次递归关系下的通解与非齐次递归关系下的特解相加,即
\[T_n = c2^n - 1.
\]
将初值 \(T_0 = 0\) 带入上式,得到 \(c=1\), 则该非齐次递归关系的解为
\[T_n = 2^n - 1.
\]
生成函数求解
设生成函数
\[g(x) = T_0 + T_1x + T_2x^2 + \cdots + T_nx^n + \cdots
\]
利用给定的递推关系和初值 \(T_0=0\),我们得到
\[\begin{align*}
g(x) - 2xg(x) &= T_0 + (T_1-2T_0)x + (T_2-2T_1)x^2 + \cdots + (T_n-2T_{n-1})x^n + \cdots \\
&= 0 + 1x + 1^2x^2 + \cdots + 1^nx^n + \cdots \\
&= -1 + (1 + x + x^2 + \cdots + x^n + \cdots) \\
&= -1 + \frac{1}{1-x}.
\end{align*}
\]
因此
\[\begin{align*}
g(x) &= \frac{1}{(1-x)(1-2x)} - \frac{1}{1-2x} \\
&= \frac{1}{1-2x} - \frac{1}{1-x} \\
&= \sum_{n=0}^{\infty}2^nx^n - \sum_{n=0}^{\infty}1^nx^n \\
&= \sum_{n=0}^{\infty}(2^n-1)x^n.
\end{align*}
\]
我们得到递推关系的解为
\[T_n = 2^n - 1.
\]
直接展开
\[\begin{align*}
T_n &= 2T_{n-1} + 1 \\
&= 2(2T_{n-2} + 1) + 1 = 2^2T_{n-2} + 2 + 1 \\
&= 2^2(2T_{n-3} + 1) + 2 + 1 = 2^3T_{n-3} + 2^2 + 2 + 1 \\
&= 2^{n-1}(2T_0 + 1) + 2^{n-2} + \cdots + 2^2 + 2 + 1 \\
&= 2^{n-1} + \cdots + 2^2 + 2 + 1 \\
&= \frac{2^n-1}{2-1} \\
&= 2^n - 1
\end{align*}
\]
汉诺塔问题拓展
问题1:是否有一种时间复杂度为 \(O(\log{n})\) 的算法计算 \(T_n \bmod p\)?(假设 \(p<2^{64}\),从而计算 \(a \bmod p, (a+b) \bmod p, (a \times b) \bmod p\) 的时间复杂度都为 \(O(1)\)。)
我们将整数 \(n\) 用二进制表示
\[n = (n_m,n_{m-1},...,n_1,n_0)_b, m = \lfloor \log n \rfloor.
\]
那么
\[n = n_m2^m + n_{m-1}2^{m-1} + \cdots + n_12^1 + n_02^0.
\]
接着
\[\begin{aligned}
T_n &= 2^n - 1 \\
&= 2^{n_m2^m + n_{m-1}2^{m-1} + \cdots + n_12^1 + n_02^0} - 1 \\
&= 2^{n_m2^m} \times 2^{n_{m-1}2^{m-1}} \times \cdots \times 2^{n_12^1} \times 2^{n_02^0} - 1.
\end{aligned}
\]
因此
\[\begin{aligned}
T_n \bmod p &= (2^n - 1) \bmod p \\
&= (2^{n_m2^m} \times 2^{n_{m-1}2^{m-1}} \times \cdots \times 2^{n_12^1} \times 2^{n_02^0} - 1) \bmod p \\
&= (\prod_{i=0}^{m} (2^{n_i2^i} \bmod p) \bmod p - 1 \bmod p) \bmod p .
\end{aligned}
\]
时间复杂度为 \(O(m)=O(\log{n})\)。