Resolving Recurrence
(1) – Substitution Method
整个recurrence就是研究一个数学表达式:T(n) = aT(n/b)+f(n) 意思是先有一个问题T(n), 解决思路为把T(n)切分成a个小问题, 每个小问题的代价是T(n/b), 然后把a个T(n/b)的结果合并起来的代价是f(n);依次类推,直到T(k)的粒度小到其复杂度是一个常数。很像是递归吧~~递归只是一种实现方式,这里介绍的是一种思路和评估这种思路复杂度的方法。
经典的评估Recurrence的方法有3种,Substitutuon, Recursion Tree和Master Method. 看下面的命题:
T(n) = 4T(n/2) + n ,需要证明T(n)=O(n2 )
Substitution:
假设T(k) <= ck2 k<n; 所以 T(n) <= 4(n/2)2 +n = n2 +n 要证明n2 +n<=cn2 好像不容易。
我们换个假设,假设T(k)<=c1 k2 -c2 k ,这样的话T(n) <= c1 n2 -(2c2 -1)n = c1 n2 -c2 n-(c2 -1)n. 所以只要 c2 >= 1,就证明成功了。注意这里,似乎没有对c1 任何限制。其实不是的!对于所有的induction方法来说,我们都需要一个初始条件,T(n0 ) = H(1) <=c1 n0 2 -c2 n0 这里我使用H(1) 代表常数复杂度。为了满足初始条件,我们需要恰当的选择 c1 ,c2 和n0 。
其实这里的初始条件就对应了算法设计里面的Base Case。Base Case就是将问题切分到最后那个粒度最小的复杂度为常数的Case。就上面的那个例子来说,c1 和c2 ,对运行时起主导作用的是前者,你在实现时设计的Base Case能使c1 越小,程序运行越快。
(2) – Recursion Tree
T(n) = T(n/3) + T(2n/3) + n
Recursion Tree其实就是Iteration,只不过图型化以后我们看起来更容易理解了。
T(n) = T(n/3) + T(2n/3) + n
= [T(n/9) + T(2n/9) + n/3] + [T(2n/9) + T(4n/9) + 2n/3]
= ……
画成图就是:
总的cost就是把每一层的cost加起来。层数就是树的高度。上面的这个问题有点tricky的。从图上看分两种情况,一种以1/3的方式减少n,还有一种是以2/3的方式。前一种方式经过log3 n次就到达叶子节点,后一种方式经过log3/2 n次,因为log3/2 n > log3 n,树的高度为log3/2 n。每一层加起来的代价是cn, 其实越到下面,每一层的cost会小于cn的,因为那时候按照1/3的方式减少的那一枝已经不存在了。
T(n) <= cn x log3/2 n = O(nlgn)
Recursion tree很直观,我们可以用它来帮助我们猜测规律,然后再用Substitution方法Double Confirm。
不过无论是Substitution还是Recursion Tree都比较烦,不能马上得出结果。有人总结了规律,叫做Mater Method。使用Master Method, 我们很快就可以直接写出T(n)=aT(n/b)+f(n)的时间复杂度。
(3) – Master Method
前面分别介绍了 Resolving Recurrence(1) – Substitution Method 和 Resolving Recurrence(2) – Recursion Tree 来评估
T(n) = aT(n/b) + f(n) 的时间复杂度。
这一节介绍Master Method,既然叫Master,可见其重要程度。掌握了Master Method,我们可以很快写出Merge Sort, Heap Sort以及Quick Sort的时间复杂度。
Master Method: (在 a>=1 并且 b>1 的情况下)
- 如果f(n) is polynomially smaller than nlog b a , polynomially smaller就是grow slower, 数学表达式f(n)=O(nlog b a-e ), e>0。 T(n) = O(nlog b a )
- 如果f(n) is polynomially same as nlog b a , T(n) = O(nlog b a lgn)
- 如果f(n) is polynomially faster than nlog b a , 并且 af(n/b) <= cf(n), c<1 && n>=b , T(n) = H(f(n)) . H表示复杂度相当。
举个例子T(n)=4T(n/2)+n , 其中a=4, b=2, –> nlog b a = n2 , 而f(n)=n, 属于第一种情况所以 T(n) = O(n2 )。 如果T(n)=2T(n/2)+n, 则属于第二种情况,T(n) = O(n lgn).
在算法导论中有详细的证明,太符号化的东西往往难以记忆,下面我们用recursion tree的方式,帮助理解和记忆。
可见, 第一层有一个节点,第二层有a的节点,第 i 层有ai 个节点,所以到叶子节点那层,叶子的个数就是 a的 树高 次幂。而树高=logb n , 我们可以很容易证明 alog b n = nlog b a 。所以一共有nlog b a 个叶子,每个叶子其实就是我们的initial condition,就是我们的base case,是整个算法的基石。
cost of all the leaves nodes = H(nlog b a )
现在对照recursion tree再来回顾一下Master Method 的 3 种情况:
1. 当所有叶子的代价比根节点高时, O(nlog b a ) > f(n), 从root到leaves,每层的cost在geometry increase,由叶子主导整个算法的时间复杂度,所以 T(n) = O(nlog b a )
2. 当所有叶子的代价和根节点相当时,表示从root 到 leaves的每一层的cost 是 几乎balance的,总代价应该是 每一层代价乘以树高, T(n) = nlog b a x logb n = H(f(n) x logb n = O(nlog b a lgn)。
3. 当所有叶子的代价比根节点低时,由根节点主导整个算法的时间复杂度。af(n/b) <= cf(n), c<1 && n>=b 表示把任务T(n)切分成a个T(n/b)的过程中,必须保证a个T(n/b)的合并代价必须小于上层任务的合并代价,并且每次切分,其单个节点的合并代价都是在减少的。简单来说就是 从root 到leaves的过程中,代价是geometry decrease的。 结论是 T(n) = H(f(n))。
Resolving Recurrence相关推荐
- IDEA中进行SpringBoot开发时提示:Error resolving template xxx, template might not exist or might not be acce
场景 IDEA中进行SpringBoot开发时提示: Error resolving template "xxx", template might not exist or mig ...
- C++实现线性递归矩阵 linear recurrence matrix算法(附完整源码)
C++实现线性递归矩阵 linear recurrence matrix算法 C++实现线性递归矩阵 linear recurrence matrix算法完整源码(定义,实现,main函数测试) C+ ...
- DNS resolving 占用大量日志
公司内部DNS配置好后,测试解析正常,只是几乎每秒都有无法解析的日志产生.但分析日志时发现,每天的日志都有2G左右.日志中几乎全是类似 network unreachable resolving 'w ...
- 解决 Idea 卡在 Resolving Maven dependencies ...
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. Idea卡在Resolving Maven dependencies的解决方案 在Reimpot A ...
- CF1182E Product Oriented Recurrence
CF1182E Product Oriented Recurrence 有一个递推式 \(f_x=c^{2x-6}\cdot f_{x-1}\cdot f_{x-2}\cdot f_{x-3}\;\; ...
- 异常:Error resolving template “xxx“, template might not exist or might not be accessible...解决办法
异常:Error resolving template "xxx", template might not exist or might not be accessible...解 ...
- 轻松解决idea一直卡在Resolving Maven dependencies的问题
原文链接:https://blog.csdn.net/weixin_43018811/article/details/103782045 关注公众号 风色年代(itfantasycc) 500G Ja ...
- Eagerly caching bean '' to allow for resolving potential circular references
tomcat启动时卡在: 一般这样的问题是两个原因: 1. 数据库连接不上: 2. mapper.xml 中有错误,比如单词拼写错误: 这个问题不是,采取的方法是 把项目的日志级别调整为debug模式 ...
- 【npm i 报错解决方法】npm ERR! code ERESOLVEnpm ERR!npm ERR! While resolving: by-web@1.2.2npm ERR!
[npm i 报错解决方法]npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! np ...
最新文章
- mysql wait_timeout 8小时问题解决,tomcat数据源的配置
- Microsoft Visual Studio (VS)2010 常用快捷键大全 便捷开发
- lolfps高但画面不流畅_你吃鸡卡吗,超详细和平精英画面设置教程,解决卡顿,主播都在用...
- android 过滤cmcc,Android 无法通过cmcc wap2.0 test解决
- Python面试题(二)
- 阿里云PolarDB论文入选数据库顶会SIGMOD2021 最新一代架构领先世界
- 再一贴[亲爱的,我不小心怀孕了~!]
- 一些dos下简单命令
- java中的构造方法与代码块
- 飞鸽传书就不去袭击你们了
- 如何快速的打造python 版的vim ide
- SC15 供应商质量管理工程师(武汉)
- solr集群solrCloud的搭建
- 图论及其应用(吴望明中文版)
- 基于LSTM-Attention模型的光伏电站发电量预估(1)
- 深入浅出计算机组成原理(四)——穿越功耗墙,我们该从哪些方面提升“性能”?
- Prometheus(二)基础概念
- Web Spider 常见混淆EVAL、AA、JJ、JSFUCK
- 使用ArchR分析单细胞ATAC-seq数据(第四章)
- Android 淡出效果手写板