算法复杂度O(nlogn)详解

来源:互联网 发布:python __iter__ 编辑:程序博客网 时间:2024/06/10 10:39

首先看以下程序段:

for(int i=1;i<=n;i++)

{

          for(int j=1;j<=n;j+=i)

           {

                   .....   //复杂度为O(1);

            }

}

求该程序段的时间复杂度。

可以看出:(1)当i=1时,需要执行n次;

                     (2)当i=2时,需要执行n/2次;

                      (3)当i=3时,需要执行n/3次;

                                .............

                      (4)当i=n-1时,需要执行n/n-1次;

                      (5)当i=n时,需要执行n/n次;

每次的时间复杂度为O(1),则总共的时间复杂度为n(1 +1/2+1/3 +1/4 + 1/5+ 1/6+1/7+1/8 +...1/n)。

1 +1/2+1/3 +1/4 + 1/5+ 1/6+1/7+1/8 +...1/n是一个调和级数。很早就有数学家研究,比如中世纪后期的数学家Oresme在1360年就证明了这个级数是发散的。Euler(欧拉)在1734年,利用Newton的成果,首先获得了这个调和级数有限多项和的值。

1+1/2+1/3+1/4+...+1/n= ln(n+1)+r(r为常量)

他的证明是这样的:
根据Newton的幂级数有:
ln(1+1/x) = 1/x - 1/2x^2 + 1/3x^3 - ...
于是:
1/x = ln((x+1)/x) + 1/2x^2 - 1/3x^3 + ...
代入x=1,2,...,n,就给出:
1/1 = ln(2) + 1/2 - 1/3 + 1/4 -1/5 + ...
1/2 = ln(3/2) + 1/2*4 - 1/3*8 + 1/4*16 - ...
......
1/n = ln((n+1)/n) + 1/2n^2 - 1/3n^3 + ...
相加,就得到:
1+1/2+1/3+1/4+...1/n = ln(n+1) + 1/2*(1+1/4+1/9+...+1/n^2) - 1/3*(1+1/8+1/27+...+1/n^3) + ......
后面那一串和都是收敛的,我们可以定义
1+1/2+1/3+1/4+...1/n = ln(n+1) + r
Euler近似地计算了r的值,约为0.5772156649。这个数字就是后来称作的欧拉常数。
回归到程序本身:

则总共的时间复杂度为:

n(1 +1/2+1/3 +1/4 + 1/5+ 1/6+1/7+1/8 +...1/n)

=n(ln(n+1) + r)

=nln(n+1)+rn

因此该程序段的时间复杂度为O(nlogn).

原创粉丝点击