前几天在JULY的博客看到一条人搜的笔试题,说是根据递归式T(N)=N+T(N/2)+T(2N),求T(N)的复杂度估计。作为一个代码功底极差、各种基础知识搓爆的卢瑟,写的各种低级程序和知识归纳实在难以出手(内流满面),就以这道题作为我博客的第一篇吧。
首先这个式子肯定是有问题的,T(N)=N + T(N/2)+T(2N)> T(2N),那不就是一个递减的序列了?还求个球的复杂度。所以正确的式子应该是
T(2N) =N+ T(N/2) + T(N) *
这个式子关联了T(2N)、T(N)、T(N/2),似乎这是一句废话。但是注意到括号里面是等比序列,从数列递推式的经验得知,这个二阶式子可以表达成一个一阶式子线性组合相加的结果。
具体来说,假设 T (N) 和 T (N/2) 的关系(善于联想是屌丝的某个属性……),于是
T(N) =αT(N/2) + βN (1)
那么将2N代入,就有
T(2N) =αT(N) + 2βN (2)
为了凑成 * 式的形式,对(1)(2)式子进行线性组合,那么应该是(α-1)(1) +(2),有
T(2N) =(α-1) βN+ α(α-1) T(N/2)+T(N) (3)
此时发现(1)式里的β参数纯属多余,写成O(N)得了(其实最后结果α = β)。那么*和(3)比对,有
α(α-1) = 1
(特马还是斐波纳契数列的特征方程),解得α=(1+sqrt(5))≈ 1.62 < 2
所以(1)式就是
T(N) =αT(N/2) +O(N)
因为logα<1,根据主定理,就有T(N) =O(N)。
做完了感觉真蛋疼,也不知道出考题的人想考些什么……
PS:重新看了下过程,感觉做得有点复杂了,把数列的特征方程重新发明了一遍,明显毫无必要,所以应该在开始的时候就做一个代换,令m = logN。然后就有了一个更蛋疼的解法:
T(2m+1) = 2m+1+T(2m-1) +T(2m) (4)
这J8式子,额……令F(m) = T(2m) - 2m+2,那么,
F(m+1) =F(m)+F(m-1) (5)
于是F(m)就是斐波纳契数列了,直接写通项公式
(6)
其中的参数α和β是由初始值决定的,α可能是负的。所以,
(7)
然后,
(8)
从(7)式就明白了这个题其实就是比较斐波那契数列和以2为公比等比数列的增长速度,我竟然蛋疼地求出了通项公式……其实尼玛估计直接画几笔就看出来了。还有,人搜很蛋疼,真心的。