一条据递推式求复杂度的笔试题

  1.       前几天在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) 的关系(善于联想是屌丝的某个属性……),于是
  1.            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为公比等比数列的增长速度,我竟然蛋疼地求出了通项公式……其实尼玛估计直接画几笔就看出来了。还有,人搜很蛋疼,真心的。

### 带有根递推的时间复杂度分析 对于带有根递推关系,通常采用的方法是通过代数变换将其转换成更易于处理的形。当遇到形如 \( T(n) = aT(\sqrt{n}) + f(n) \) 的递推方程时,可以考虑引入新的变量来简化表达[^1]。 令 \( m=\log n \),则原递推变为: \[ S(m)=aS\left( \frac{m}{2} \right)+f(e^{m}) \] 这里定义了新函数\( S(m):=T(e^m)\)。这种变化使得原本难以直接应用主定理的根号形转化为指数形,从而可能适用其他已知的结果或技术来进行解。 为了进一步具体化这一过程,假设给定了具体的常量\( a \)以及函数\( f(n) \),可以根据具体情况调整上述方法中的细节部分。如果\( f(n) \)是一个多项,则可以通过比较增长速度确定最终的大O记号;如果是更加复杂的非线性项,则可能需要用到额外的技术手段比如展开泰勒级数或者其他近似技巧。 ```python import math def analyze_recurrence(a, func_f, max_n): """ 分析具有平方根特性的递归时间复杂度 参数: a (int): 递归系数 func_f (function): 非递减成本函数 max_n (float): 输入规模上限 返回: str: 时间复杂度估计 """ log_max_m = int(math.log(max_n)) def s(m): if m == 0: return func_f(1) else: half_m = m // 2 return a * s(half_m) + func_f(pow(2,half_m)) result = s(log_max_m) # 这里仅作为示意,实际应基于s(m)的具体形态给出大O描述 complexity_guess = "待补充" return complexity_guess # 示例调用 print(analyze_recurrence(2, lambda x : x*x , pow(2,8))) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值