『数学杂谈』递归式复杂度求解

关于递归式复杂度求解的一些想法。

虽然说具体数学有一整章讲渐进式,但鉴于学这个性价比太低了,基本也用不到,所以很多有关渐进式的东西会在本文总结。

接下来进入正题。

主定理的局限性

  这是本文十分重要的一个点。这里先贴一下主定理,为了使文章尽可能简洁,就不贴出证明了:

  主定理的适用范围是非常广的,但是它对下面这个式子束手无策:

\[\begin{flalign} \label{1} T(n) = 4\sqrt nT(\sqrt n)+n \end{flalign} \]

  发现主定理用不了,因为子问题里的 \(\sqrt n = \frac{n}{\sqrt n}\) 得到 \(b\) 并不是一个常数,此时主定理就(萎了)用不了了。
  你以为我接下来要说怎么做了,但我还要继续乳主定理(),看到下面这个递归式

\[\begin{flalign} \label{2} T(n) = T(\frac n2)+T(\frac n4)+T(\frac n8)+n \end{flalign} \]

这个式子的子问题并不是平均划分的,因此也就不能用主定理。
  好事成三,我们再看一个式子:

\[\begin{flalign} \label{3} T(n)=4T(\frac n4)+\frac n{\lg n} \end{flalign} \]

此时该式子不符合主定理的三种情况,也是不能用主定理的。
  (虽然但是主定理在一般情况下还是非常好用的啦)

不那么暴力的暴力

  对于不能用主定理解决的递归式,《算法导论》中推荐使用递归树+数学归纳法解决,但是这样工作量过于巨大了,会显得很蠢,还不如乱猜再证明来的快,此时就十分的难受,不知道怎么整。
  为了让我们能更简洁与优美的暴力,采用更好的方法是必要的。我们尝试在递归树的基础上进行优化。就像记忆化搜索可以优化深度优先搜索一样,我们可以对每一个可能出现的子问题考虑它对答案的贡献。
  拿 \((1)\) 式举例,我们无需列出一整棵递归树,只需对每个子问题统计贡献即可。用 \(w(x)\) 表示子问题 \(T(x)\) 的贡献,就可以有下面的表:

\(x\) \(w(x)\)
\(n\) \(n\)
\(\sqrt n\) \(4\sqrt n \times \sqrt n = 4n\)
\(\sqrt {\sqrt n}\) \((4\sqrt {\sqrt n})(4\sqrt n )(\sqrt {\sqrt n}) = 16n\)

  相信对数字敏感的人无需列表即可感性地证明规律,即使不太敏感,表的前三项也足够找到规律:

\[w(n^{0.5^x}) = 4^xn \]

那么设 \(n=2^k\) 那么层数就应该是:

\[\log_2 k = \log_2 \log_2n \]

总的复杂度就会是:

\[\sum\limits_{i=0}^{\log_2 \log_2n}4^in \]

\(\sum\limits_{i=0}^{\log_2 \log_2n}4^i \sim 4^{\log_2 \log_2n}\)
所以答案为

\[\begin{array}{ll} 4^{\log_2 \log_2n}n &= 2^{2\log_2 \log_2n}n\\ &= (2^{\log_2 \log_2n})^2n\\ &= \mathcal O(n(\log^2n)) \end{array} \]

  不够劲?不妨再来一组。我们来解决式 \((2)\) ,而这甚至表都可以不列出来。不难发现层数最为 \(\log_2n\) ,而层贡献为 \(层值 \times 层出现次数\) ,假设当前层为 \(n\frac 1{2^k}\) ,相当于一次能走一步、两步或三步,走 \(k\) 步的方案数, \(OGF\) 搞起,但是没搞出来(?),但是可以从组合的角度近似地看作把 \(k\) 个数分成三段,那么这个系数就应该是 \(\mathcal O(k^2)\) 的,那么答案就是:

\[\sum\limits_{i=0}^{\log_2n}i^2\frac 1{2^i}n = \mathcal O(n) \]

  最后我们来搞定式 \((3)\) ,依然是把层数算出来,是 \(\log_4n\) ,那么答案就是:

\[\sum\limits_{i=0}^{log_4n}4^i\frac {\frac n{4^i}}{\lg \frac n{4^i}} = \sum\limits_{i=0}^{log_4n} \frac {n}{\lg \frac n{4^i}} \]

然后我就不会做了……那么这时候就应该开!()

Akra-Bazzi定理


  其中的多项式增长条件可以简易地理解为 \(\exists c>0,|g'(x)|\in \mathcal O(x^c)\)
  开了之后我们再回到式 \((3)\)\(p\) 显然为 \(1\) ,那么代入定理得到:

\[\begin{array}{ll} T(n) &= \Theta\left(n\left(1+\int^n_1\frac {\frac x{\lg x}}{x^2}dx\right)\right)\\ &= \Theta\left(n\left(1+\int^n_1\frac {1}{x\lg x}dx\right)\right)\\ &= \Theta(n+(1+\lg\lg n))\\ &= \Theta(n\lg\lg n) \end{array} \]

  Akra-Bazzi定理原论文里的证明用了一种称为阶变换(Order Transform)的技巧,还涉及泛函分析,会不了一点。当然粗暴一点的方法有数学归纳法,但是也不想写,或许等我过个一两年上大学之后再填坑(?)

总结

  总结一下,对于一般的递归式,可通过主定理求渐进解。而对于 \(b\) 不是常数的情形,分层分析贡献。最后对于 \(g(n)\) 满足多项式增长的式子,用Akra-Bazzi莽。
  (感觉这篇写的好水)

posted @ 2023-09-15 22:16  Black_Crow  阅读(25)  评论(0编辑  收藏  举报