时间复杂度的计算分析

它通常是计算程序执行过程中赋值和比较操作的次数。一般只考虑赋值情况。

考虑最好、平均和最坏的情况。

例a.对数组中所有元素求和

for(i=0,sum=0;i<n; i++)
        sum+=a[i];

分析:

先初始化两个变量i和sum,然后执行n次for循环,每次循环中,都会进行两次的赋值(sum,i++),循环结束后一共进行了2+2n次赋值,因此这个算法的渐近复杂度为O(n)。

 

例b.嵌套循环

for(i=0;i<n;i++)
        for(j=1,sum=a[0];j<=i;j++)
               sum+=a[j];

分析:

先初始化i,然后外循环执行n次,在外层循环的每次迭代中都执行内层的for循环,给j、i、sum赋值,对于每一个i,内层循环都会执行i次,在每次的迭代中,都会进行两个赋值,一个是对sum,一个是对j赋值,因此程序总共进行了次。

 

例c.二分查找算法分析

int binarySearch(int a[], int len, int key)
{
        int low=0,high=len-1;
        int mid;
        while(low<high)
       {
               mid=(low+high)/2;
               if(a[mid]<key)
                      low=mid+1;
               else if(a[mid]>key)
                      high=mid-1;
               else
                      return mid;
        }
        return -1;
}    

分析:

如果key正好位于数组的正中间,则循环只执行一次;如果key不在数组中,如何考虑?首先数组长度为n,数组的一半是n/2,一半的一半是n/,以此类推直到数组的长度为1。于是得到数列n,n/2,n/…,n/,只要知道m的值就好,n/2m=1,得到m=lgn。

例d.考虑递归情况


1. 递归实现机制 
    每一次递归调用,都用一个特殊的数据结构
"栈"记录当前算法的执行状态,特别地设置地址栈,用来记录当前算法的执行位置,以备回溯时正常返回。递归模块的形式参数是普通变量,每次递归调用得到的值都是不同的,他们也是由"栈"来存储。 
2. 递归算法效率分析方法
 
   递归算法的分析方法比较多,最常用的便是迭代法。
 
  迭代法的基本步骤是先将递归算法简化为对应的递归方程,然后通过反复迭代,将递归方程的右端变换成一个级数,最后求级数的和,再估计和的渐进阶。 
 递归方程有如下几种形式:
 (a)递归方程为: T(n) = T(n - 1) + O(1);   这个例子的时间复杂性是线性的。
         迭代展开: T(n) = T(n - 1) + O(1) 
                               = T(n - 2) + O(1) + O(1) 

                              = T(n - 3) + O(1) + O(1) + O(1) 
                               = ...... 
                               = O(1) + ... + O(1) + O(1) + O(1) 
                               = n * O(1) 
                               = O(n) 
 b 递归方程:T(n) = 2T(n/2) + 2, 且假设n=2k次方。 时间复杂度是线性的
         迭代展开:T(n) = 2T(n/2) + 2 
                                 = 2(2T(n/2*2) + 2) + 2 
                         = 4T(n/2*2) + 4 + 2 
                         = 4(2T(n/2*2*2) + 2) + 4 + 2 
                         = 2*2*2T(n/2*2*2) + 8 + 4 + 2 
                         = ... 
                         = 2k+2k-1+2k-2+…+2
                         =2 * n - 2 
                         = O(n) 
  (c)递归方程: T(n) = 2T(n/2) + O(n), 且假设n=2的k次方。 
         迭代展开:
 T(n) = 2T(n/2) + O(n) 
                           = 2*2T(n/4) + 2O(n/2) + O(n) 

                                            =2*2*2T(n/8) + 2*2O(n/4)+2O(n/2) + O(n) 
                               = ... 
                               = O(n) + O(n) + ... + O(n) + O(n) + O(n) 
                               = k * O(n) 
                               = O(k*n) 
                               = O(nlog2n)   //2为底 


      一般地,当递归方程为T(n) = aT(n/c) + O(n), T(n)的解为: 
      O(n)                                (a<c && c>1) 
      O(nlog2n)                      (a=c && c>1) //以
2为底 
      O(nlogca)                      (a>c && c>1) //n的
(logca)次方,以c为底 
   上面介绍的
3种递归调用形式,比较常用的是第一种情况,第二种形式也有时出现,而第三种形式(间接递归调用)使用的较少,且算法分析 比较复杂。 下面举个第二种形式的递归调用例子。 
  (d)递归方程为:T(n) = T(n/3) + T(2n/3) + n 
     为了更好的理解,先画出递归过程相应的递归树: 
                            n                        --------> n 
                  n/3            2n/3              --------> n 
          n/9       2n/9   2n/9     4n/9         --------> n 
           ......     ......  ......  .......        ...... 
                                                     -------- 
                                                     总共O(nlogn) 
     累计递归树各层的非递归项的值,每一层和都等于n,从根到叶的最长路径是: 
      n --> (2/3)n --> (4/9)n --> (12/27)n --> ... --> 1 


     设最长路径为k,则应该有: 
     (2/3)的
k次方 * n = 1             得到 k = log(2/3)n  // 以(2/3)为底 
     于是
 T(n) <= (K + 1) * n = n (log(2/3)n + 1) 
     即 T(n) = O(nlogn) 
    由此例子表明,对于第二种递归形式调用,借助于递归树,用迭代法进行算法分析是简单易行的。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值