算法分析中经常遇到需要求解递推式的情况,即将递推式改写为等价的封闭形式。例如汉诺塔问题的时间复杂度递推形式为T(n)=2T(n−1)+1(n≥1)T(n)=2T(n−1)+1(n≥1),可以解出封闭形式为T(n)=2n−1T(n)=2n−1(设初始状态T(0)=0T(0)=0)。

因为递推式求解的重要性,许多算法书籍对其有专门介绍。Donald Knuth在Concrete Mathematics一书中多个章节都涉及递推式求解方法。算法导论也在第四章中专门论述的这个主题。

在这些相关论述中,主要介绍了一些启发式方法,这些方法往往需要一些特殊的技巧和灵感才能完成。

而本文将论述一种纯代数式的方法,这种方法将求解递推式转化为求解一个多项式的根和求解一组线性方程组,这样就使得整个求解过程不依赖于太多技巧,因此具有更好的易用性。

本文首先会给出两个例子:如何使用纯代数方法求解斐波那契数列和汉诺塔递推式;然后会借助线性代数论述这种方法背后的数学意义,说明线性递推式与线性方程的内在联系以及这种解法的数学原理;最后将例子中的方法推广到一般情况。

示例

例1:斐波那契数列

斐波那契数列大家应该很熟悉了,这里不再赘述,直接进入问题。

问题

设斐波那契数列为由如下递推式定义的数列:

T(0)T(1)T(n)===01T(n−2)+T(n−1)(n≥2)T(0)=0T(1)=1T(n)=T(n−2)+T(n−1)(n≥2)

求解T(n)T(n)的封闭形式(也就是斐波那契数列的通项公式)。

求解

首先忽略初始条件,考虑递推式T(n)=T(n−2)+T(n−1)T(n)=T(n−2)+T(n−1)。可以对解的形式进行一个猜测T(n)=qnT(n)=qn(这个不是瞎猜的,实际上可以证明线性递推式都遵循这种形式)。那么,递推式可以重写为:

⇒⇒⇒T(n)=T(n−2)+T(n−1)qn=qn−2+qn−1q2=1+qq2−q−1=0T(n)=T(n−2)+T(n−1)⇒qn=qn−2+qn−1⇒q2=1+q⇒q2−q−1=0

这样问题被转化为一个一元二次方程的求根问题。利用求根公式可得:

q=1±5√2q=1±52

因此得到递推式的一个通解:

T(n)=c1(1+5√2)n+c2(1−5√2)nT(n)=c1(1+52)n+c2(1−52)n

即其中c1c1和c2c2为任意实数。下一步要代入初始条件解出c1c1和c2c2。根据n为0和1时的初始条件,可得:

{c1+c2c1(1+5√2)+c2(1−5√2)==01{c1+c2=0c1(1+52)+c2(1−52)=1

解得c1=15√c1=15,c2=−15√c2=−15。因此最终解为:

T(n)=15√((1+5√2)n−(1−5√2)n)T(n)=15((1+52)n−(1−52)n)

例2:汉诺塔

汉诺塔的时间复杂度通常使用递归式定义,在这个例子中将使用代数方法求解其封闭形式。

问题

汉诺塔的时间复杂度为T(n)=2T(n−1)+1T(n)=2T(n−1)+1,求解其封闭形式。

求解

这里并不能直接使用例1中的方法,因为右边除了递推项外,还有一个非递推项1,用线性代数的语言说,这个线性递推式是非齐次的。

可以回想一下线性代数中求解非齐次方程组通解的方法:1)求解其齐次部分的通解。2)求其一个特解,将特解加到通解上即得非齐次方程组通解。

我们用类似的方法求解汉诺塔时间复杂度递推式。首先,忽略后面的1,则得到一个齐次线性递推式:

T(n)=2T(n−1)T(n)=2T(n−1)

转化为多项式方程:

⇒⇒T(n)=2T(n−1)qn=2qn−1q=2T(n)=2T(n−1)⇒qn=2qn−1⇒q=2

因为方程是一次多项式,我们直接得到了其解为2。因此齐次递推式的通解为c2nc2n,其中c为任意常数。

然后我们需要求得T(n)=2T(n−1)+1T(n)=2T(n−1)+1的一个特解,解是一个以n为变量的函数。我们可以先从常数试起,设特解为T(n)=aT(n)=a,带入得a=2a+1a=2a+1, 解得a=−1a=−1。因此,原递推式的通解为:

T(n)=c2n−1T(n)=c2n−1

最后我们求解常数c。

将初始条件T(0)=0T(0)=0带入,得0=c−10=c−1,因此c=1c=1。代入原通解,得汉诺塔时间复杂度递推式的封闭形式为:

T(n)=2n−1T(n)=2n−1

数学原理

上面两个例子可能有些同学看的不是很明白,其中提到了一些线性代数术语。在这一章节中,我们分析上述解法的数学原理,看看递推式是如何与线性代数关联起来的。

线性递推式的一般化

斐波那契数列和汉诺塔递推式可以看成线性递推式的特例,下面给出线性递推式的一般定义:

我们将满足如下递推关系的递推式称为线性递推式:

T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)+C(n)T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)+C(n)

其中C(n)C(n)是只与n有关系的一个函数。如果C(n)=0C(n)=0,则称递推式为齐次此,否则称为非齐次的。齐次递推式一定有平凡解T(n)=0T(n)=0。

注意仅有递推式是不能求得T(n)T(n)的唯一解,因此递推关系式只能给出一个通解。只有当下列初始条件确定后,才有可能给出T(n)T(n)的唯一特解。

T(0)=b0T(1)=b1⋮T(k−1)=bk−1T(0)=b0T(1)=b1⋮T(k−1)=bk−1

齐次递推式求解定理

下面先考虑齐次线性递推式的求解。定理如下:

设有线性齐次递推式T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)

另设多项式方程qk−a1qk−1−⋯−ak−1q−ak=0(q>0,ak≠0)qk−a1qk−1−⋯−ak−1q−ak=0(q>0,ak≠0)的根是 q1,q2,…,qkq1,q2,…,qk,我们先讨论不存在重根的情况,也就是说k个根互不相等。

则T(n)T(n)的通解为:

T(n)=c1qn1+c2qn2+⋯+ckqnkT(n)=c1q1n+c2q2n+⋯+ckqkn

并且对于任意的初始情况

T(0)=b0T(1)=b1⋮T(k−1)=bk−1T(0)=b0T(1)=b1⋮T(k−1)=bk−1

都存在一组解c1,…,ckc1,…,ck使得递推式成立

定理的证明

要证明以上定理,主要需要证明两部分。一是证明多项式根的线性组合可以满足递推式,二是证明任意初始条件下总有解。

可满足性证明

首先来证明T(n)=c1qn1+c2qn2+⋯+ckqnkT(n)=c1q1n+c2q2n+⋯+ckqkn可以满足递推式。

T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)经过变换可以改写为 T(n)−a1T(n−1)−a2T(n−2)−⋯−ak−1T(n−k+1)−akT(n−k)=0T(n)−a1T(n−1)−a2T(n−2)−⋯−ak−1T(n−k+1)−akT(n−k)=0

假设T(n)=qnT(n)=qn,因为q>0q>0,所以两边除以qn−kqn−k,得到qk−a1qk−1−⋯−ak−1q−ak=0qk−a1qk−1−⋯−ak−1q−ak=0

因此这个多项式和原递推式同解,因此多项式的每个根q的几何级数qnqn都是原递推式的一个解。同时,根的线性组合 c1qn1+c2qn2+⋯+ckqnkc1q1n+c2q2n+⋯+ckqkn均满足原递推式(可以带入验证)。

任意初始值有解证明

下面要证明对于任意初始条件,均存在适当的常数c1,…,ckc1,…,ck。

T(0)=b0T(1)=b1⋮T(k−1)=bk−1T(0)=b0T(1)=b1⋮T(k−1)=bk−1

带入通解公式,得到一个线性方程组

c1+c2+⋯+ckc1q1+c2q2+⋯+ckqkc1q21+c2q22+⋯+ckq2k⋮c1qk−11+c2qk−12+⋯+ckqk−1k====b0b1b2bk−1c1+c2+⋯+ck=b0c1q1+c2q2+⋯+ckqk=b1c1q12+c2q22+⋯+ckqk2=b2⋮c1q1k−1+c2q2k−1+⋯+ckqkk−1=bk−1

此时问题转化为证明此方程组对于必然有解,下面就要用到线性代数的知识了。这个方程组的系数行列式为:

det(V)=∣∣∣∣∣∣∣∣1q1q21⋮qk−111q2q22⋮qk−12……………1qkq2k⋮qk−1k∣∣∣∣∣∣∣∣det(V)=|11…1q1q2…qkq12q22…qk2⋮⋮…⋮q1k−1q2k−1…qkk−1|

这个行列式就是非常著名Vandermonde行列式,所以

det(V)=∏1≤i<j≤k(qi−qj)det(V)=∏1≤i<j≤k(qi−qj)

上面我们假设了多项式各个根均互异,因此行列式的值不等于0,这意味着系数矩阵的秩为k。有线性代数知识可知,这表明 对于任意初始值b0,…,bk−1b0,…,bk−1,方程组均有唯一解。

证毕。

顺便说一下,上面的多项式叫特征多项式。其根叫特征根。

通用解法

通过上面的数学分析,我们得到了一个解线性递推式的通用方法。

齐次递推式

设有齐次递推式

T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)

我们可以写出其特征多项式方程

qk−a1qk−1−⋯−ak−1q−ak=0(q>0,ak≠0)qk−a1qk−1−⋯−ak−1q−ak=0(q>0,ak≠0)

解出其k个根q1,…,qkq1,…,qk。如果k个根互异(但可以有复根),则原递推式的通解为

T(n)=c1qn1+c2qn2+⋯+ckqnkT(n)=c1q1n+c2q2n+⋯+ckqkn

然后将初始条件b0,…,bk−1b0,…,bk−1带入组成线性方程组

x1+x2+⋯+xkx1q1+x2q2+⋯+xkqkx1q21+x2q22+⋯+xkq2k⋮x1qk−11+x2qk−12+⋯+xkqk−1k====b0b1b2bk−1x1+x2+⋯+xk=b0x1q1+x2q2+⋯+xkqk=b1x1q12+x2q22+⋯+xkqk2=b2⋮x1q1k−1+x2q2k−1+⋯+xkqkk−1=bk−1

解线性方程组得唯一解x^1,…,x^kx^1,…,x^k。带回通解公式则得到递推式的最终解

T(n)=x^1qn1+x^2qn2+⋯+x^kqnkT(n)=x^1q1n+x^2q2n+⋯+x^kqkn

非齐次递推式

对于非齐次递推式

T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)+C(n)(C(n)≠0)T(n)=a1T(n−1)+a2T(n−2)+⋯+ak−1T(n−k+1)+akT(n−k)+C(n)(C(n)≠0)

可以首先按上面的方法求解其齐次部分的通解TnTn。然后求得其一个特解ynyn,则非齐次递推式的通解为

Tn+ynTn+yn

然后用同样的方法带入初始值,通过线性方程组求出个常量参数带回即可(具体可参见例2)。

有重根的情况

上面的解法只针对特征根互异,如果有重根的话,则上述方法会无效。不过只要经过一定处理也可以有通用方法求解, 因有点复杂,本文不在针对重根情况进行叙述。关于重根情况下的求解,有感兴趣的同学可以参考线性代数或微分方程相关文献。

from: http://blog.codinglabs.org/articles/linear-algebra-for-recursion.html

算法分析中递推式的一般代数解法相关推荐

  1. 【笔记】从递推式得到通项公式的几种方法

    开头瞎扯 数列这玩意在竞赛中考的不少,可以变形一些式子,所以做一个小总结 如果题目中出现了一个数列的式子,将其化为通项公式有可能可以快速求解或者是便于题目变形并发现题目性质 解题套路 对于大部分情况来 ...

  2. 【递推法】错排问题的递推式和推导过程

    [递推法]错排问题的递推式和推导过程   前言:这篇博客是帮助没有见过错排的新人更好的理解错排问题的递推式和推导过程,各位大佬可自行跳过 题目链接:洛谷P1595信封 一.错排问题的定义:   很多人 ...

  3. UVA - 10253 Series-Parallel Networks(递推式、记忆化搜索写法)

    题目:UVA-10253 题目翻译(来自蓝书): 串并联网络有两个端点,一个叫源,一个叫汇,递归定义如下: (1) 一条单独的边是串并联网络. (2) 若G1和G2是串并联网络,把它们的源和源接在一起 ...

  4. 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)

    这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...

  5. AcWing 885. 求组合数 I(递推式预处理)

    题面连接 https://www.acwing.com/problem/content/887/ 思路 通过组合数学的知识我们能知道Cab=Ca−1b+Ca−1b−1C_a^b = C_{a-1}^b ...

  6. 【组合数学】二项式定理与组合恒等式 ( 二项式定理 | 三个组合恒等式 递推式 | 递推式 1 | 递推式 2 | 递推式 3 帕斯卡/杨辉三角公式 | 组合分析方法 | 递推式组合恒等式特点 )

    文章目录 一.二项式定理 二.组合恒等式 ( 递推式 1 ) 三.组合恒等式 ( 递推式 2 ) 四.组合恒等式 ( 递推式 3 ) 帕斯卡 / 杨辉三角公式 五.组合分析方法 六.递推式组合恒等式特 ...

  7. [递推式求解、多指针、前缀和]XATU第七届算法大赛

    文章目录 赛后感想 1.2题略 3 乐华水上梦幻乐园之拖鞋失踪案[概率论.递推式求解] 题意 分析 代码 4.5.6.7.8题略 9 Ugly Number[多指针] 题意 做法1[BFS with ...

  8. 虽说是递推式,但我还是觉得是逆推法

    母牛的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  9. Tyche 2191 WYF的递推式

    题目描述 WYF手中有这样一条递推式 WYF并不是想让你帮他做出结果,事实上,给定一个n,他能够迅速算出Fn.WYF只是想单纯的考验一下读者们. 输入描述 仅一行,三个整数N,F1,P 输出描述 仅一 ...

最新文章

  1. ADB命令行控制界面开关
  2. oracle数据库怎么导出dat文件_论将数据从数据库导出为dat格式.docx
  3. vue2.0小示例一个~~新鲜出炉哦。欢迎大家留言
  4. 揭秘 MWU 最佳画质游戏《永劫无间》技术历程
  5. 固有属性与自定义属性
  6. 华为发布会: 牛逼鸿蒙,吹水的大会
  7. DataGridView 中合并单元格
  8. es6 Object.getPrototypeOf()方法
  9. 解决Golang程序运行时占用内存不断增加的问题
  10. ubuntu 8.10 可用的源
  11. C语言制作简单计算器
  12. flexray VPX控制板设计方案详细
  13. SVM支持向量机原理总结
  14. (实战)Node.js 实现抢票小工具短信通知提醒
  15. 暑假实训-3_Oracle数据库-3_单行函数
  16. Python math.erfc() 方法
  17. 研发效能度量框架解读
  18. 关于“指定的参数已超出有效值的范围。参数名 utcDate”的解决方案
  19. 谈谈本科生和研究生的差距
  20. Scala知识点总结(上半部分)

热门文章

  1. 感受亚马逊:“抠门”的巨无霸电商如何炼成
  2. 如何向新手程序员介绍编程?
  3. 织梦调用css的标签,织梦dede常用的调用标签(个人总结)
  4. Quartz-JobListener解读
  5. mysql创建新用户方法_Mysql创建新用户方法
  6. ca开头的车是什么牌子_动车与高铁的区别是什么?很少人知道!让我来告诉你吧...
  7. 图像混合模式:Android Paint Xfermode 使用和demo
  8. 赌徒都应该明白的道理:通过简单计算告诉你为什么久赌必输
  9. 不定高度的弹框 垂直水平居中
  10. pythondjango项目集成_[Python]将Wagtail整合到Django2项目中