软考—从分治法中看时间复杂度计算

来源:互联网 发布:java invoke 返回空 编辑:程序博客网 时间:2024/04/29 09:33

1)分治策略的思想和理论



        分治算法是按照下列方案来工作的:


        1、将问题的实例划分为几个较小的实例,最好具有相等的规模(事实上,一般来说就是这样来分的,而且分为2个实例的居多,注意是递归的分!!!)


        2、对这些较小的实例求解(一般使用递归的方法,但在问题规模足够小的时候也可以采用采用另一个算法(停止递归))


        3、如果有必要的话,合并这些较小问题的解,以得到原始问题的解(事实上,一个分治算法的精华就在于合并解的过程)


        不要忽视这三句话!!!它是许多分治算法经验的总结,有助于在分析问题中考虑如何去使用分治算法,提请注意括号里我的注释!!!


        形象的表示一下,截张图:









        大多数都是规模为n的问题,被划分为2个规模为n/2的问题,更一般的情况下,从理论上分析一下:


        一个规模为n的实例可以划分为b个规模为n/b的实例,其中a个实例是需要求解的,为了简化分析,我们假设n是b的幂(每次都可以整的划分),对算法的运行时间,下面的递推关系式是显然的:






        其中,a,b的含义已经说过了,f(n)表示将求解得到的a个子问题的解合并起来所需要的时间复杂度。


        如何根据a,b以及f的阶来确定这个算法的时间复杂度呢?有下列主定理:(证明参见算法导论)








2)定理分析



          1、b,a,f(n)的含义,这个要弄清楚,要不然恐怕你是无法记住这个结论的。


        2、这个式子是一个通用的数学表达式,在计算机的常用算法策略中,它太概括了,我们往往用到的只是它范围很小的一部分。


        分析1:a和b的关系,其实a绝大多数时候都是等于b的吧(因为规模n划分为了b个子规模,需要处理的是a个,参见a,b的含义),a,b的含义告诉我们a <= b(当这是最基本要满足的条件)。常常要么是 a==b(分成的子规模都要处理,然后去合并),要么是a==1(实际上这是减治的思想,分成了b个子规模,但最终却可以排除其他的,只在其中一个子规模中去处理)。一般来说就是这样,所以a,b并不是随意的。




        分析2:其实b要么为2(几乎所有情况)要么为3(极少数情况)吧,这个分治思想里面就说啦,一般来说都是分为2个规模相等的子规模(当然谁都想分的越多越好,这样算法就更快,但是现实是问题往往没有那么高效的算法,找到一个3的分治就已经很不错了)




        分析3:由上面2条可知,a,b的值几乎就那么几个(当然我说的是几乎所有书上可以看到的常见算法案例),所以不用那么担心。




        分析4:f(n)是线性的的情况很多(即d=1的情况是最多的)。再来看看a和b^d比较大小的关系说明了什么:f(n)代表的是合并的复杂度,1<=a <= b,定性的分析,可以知道:


        第一种情况:a < b^d


        因为1<=a <= b,所以只要d>1,不管a,b是什么(不管怎么划分规模,也不关需要处理几个规模),总是第一种情况,时间复杂度是n^d。如果d=1呢,只要a < b(处理的比划分的少),那么还是第一种情况,时间复杂度也是n^d = n


        第二种情况:a =  b^d


        因为1<=a <= b,所以如果a=b(划分多少处理多少),那么d只能为1才能是这种情况。-----常见的归并排序都是这样而如果a < b,那b就只能<1才能是这种情况,一般很少见。


        第三种情况:a  >  b^d


        非常少见,我还木有见过这样的算法,一开始我认为这种情况不可能,但在理论上它是存在的。因为1<=a <= b,所以要满足这个式子d必须<1 。


        从这也可以看出这三个参数之间的关系,事实上是划分的复杂度和合并的复杂度在争抢复杂度的控制权。


        说了这么多,感觉越分析越复杂了吗,其实不是,把这些分析想清楚,对递推式的理解就更进一步了,有了上述分析,其实下面几个常见的递推式就包含了大多数的算法:


        T(n)  =   a * T(n/b)  +  f(n)的常见式子:




        1、T(n)  =  2 * T(n/2) + O(n)      时间复杂度n*log(n)


        一般来说分治算法就是这样,分成2个子规模的问题,需要处理的也是2个,对这两个子规模合并又是线性的
        a = b = 2,    d = 1;        a == b^d 由主定理得n*log(n)


        只要a=b,d=1,就都是这个复杂度

        2、T(n)  =  T(n/2) + O(n)        时间复杂度为n,线性的


        a = 1,b = 2,d=1(分为2个子规模,但只对一个子规模处理,合并也是线性的)


        a < b^d,      时间复杂度是n^d = n


        其实质押a < b,d=1,都是这个。

        感觉对一个定理解读了这么多,确实让它变得更加复杂了,但如果你做了上述思考,相信对这个式子认识也更加深刻了一点。
1 0
原创粉丝点击