分治策略

  2018-5-27 


对分治策略的分析见文章[递归分析]http://aisakaki.com/?p=406

1、分解(分)

2、解决(治)

3、合并

一些使用分治策略的算法

①归并排序

T(n)=2T(n/2)+Θ(n)

2为子问题数目,n/2为子问题规模,Θ(n)为附加计算量(分治法运行时间)

通过主定理case2,可以得到其T(n)=O(nlgn)

②二分查找

分:二分

治:比较。只在一个子数组中递归

T(n)=1*T(n/2)+Θ(1)

1个子问题

③乘方问题

求x^n

如果用朴素方法,那么T(n)=O(n)

如果采用分治策略,那么T(n)=T(n/2)+Θ(1)=O(lgn) (master method) <O(n)

*注意奇偶n的处理,但其递归式不变

只有一个子问题,画递归树的话就是一条链

④非不拉几数列

Fn=Fn-1 + Fn-2 if n>=2

Fn=0 if n=0

Fn=1 if n=1

1*若采用朴素的递归方式,不停计算Fn-1,Fn-2,触底就返回,那么

T(n)=Ω(φ^n) φ=(1+√5)/2 (φ为黄金比例,神奇)

子问题的规模仅仅缩小到了n-1,递归树非常庞大

复杂度为指数级,代价很高,所以此种方法不好。

最理想的算法复杂度为多项式级

2*事实上,在建立非不拉几递归树的时候,会发现很多公共子树,这些子树重复计算,产生了大量冗余。

如果考虑从底向上计算(线性。依次计算F(1),F(2),F(3),….),那么其复杂度会是O(n)

3*有一个更简单的办法(数学),F(n)=φ^n/√5并取整至最接近的整数,复杂度即为③中的问题,为O(lgn)

由于φ为浮点数,所以这样不精确且对运算要求极高,在现有机器上无法运行

4*第二种数学方法

Fn-1 Fn = 1 1 ^n

Fn Fn-2 = 1 0

(左右皆为矩阵,右边是矩阵的n次幂,待安装数学公式插件再修改)

证明:数学归纳法。比较简单,证略。

其复杂度为O(lgn)

⑤矩阵乘法

朴素方法:三层循环,i对应左行,j对应右列,k对应遍历每个元素。T(n)=O(n^3)

分治方法1:

利用分块矩阵,将母矩阵变成2*2的矩阵

A= A11 A12

A21 A22

B=B11 B12

B21 B22

C=C11 C12

C21 C22

由此可以写得四个表达式

c11=A11B11 + A12B21

C12=A11B12+A12B22

C21=A21B11+A22B22

C22=A21B12+A22B22

由此可得每次递归需要将有八个递归子问题(乘),并加上4次矩阵加法时间

(8个规模为n/2的矩阵乘法(递归)和4个规模为n/2(即合并起来为一个规模为n)的矩阵加法(非递归,常数)

所以其递归表达式为 T(n)=8T(n/2)+Θ(n^2)

由主定理得,T(n)=Θ(n^3)

此方法效率依然很低,和朴素方法没什么区别。

思考:为什么效率低?

因为矩阵乘法是Θ(n^3)级复杂度,而一次递归将产生8个子问题,每个子问题皆矩阵乘法

而矩阵加法是Θ(n^2)级复杂度。所以为了使递归树变小,我们应尽量减少矩阵乘法,多做矩阵加法。

比如,一次递归产生8个子矩阵乘法问题,递归树太“茂盛”了,我们能否减小到7个?

通过这种思考下去,就想到了第二种方法

分治方法2:Strassen方法

该算法具体内容见https://blog.csdn.net/qwertyuer/article/details/44255087

该算法下,T(n)=7T(n/2)+Θ(n^2)=Θ(n^lg7)<Θ(n^3)

分:将AB 矩阵分为8个子矩阵

治:中间计算过程

合:将子问题的解合并为原问题的解

未完待续


且听风吟