zoukankan      html  css  js  c++  java
  • 时间复杂度

           1, 算法分为时间复杂度和空间复杂度;

    作用: 时间复杂度是度量算法运行的时间长短。而空间复杂度是度量算法所需存储空间的大小。
      2. 普通情况下,算法的基本操作反复运行的次数是模块n的某一个函数f(n),因此。算法的时间复杂度记做:T(n)=O(f(n))
      分析:随着模块n的增大。算法运行的时间的增长率和f(n)的增长率成正比。所以f(n)越小,算法的时间复杂度越低,算法的效率越高。


      3. 在计算时间复杂度的时候,先找出算法的基本操作,然后依据对应的各语句确定它的运行次数。再找出T(n)的同数量级(它的同数量级有下面:1,Log2n 。n 。nLog2n ,n的平方,n的三次方。2的n次方,n!),找出后。f(n)=该数量级,若T(n)/f(n)求极限可得到一常数c,则时间复杂度T(n)=O(f(n))

     

      例:算法:

      for(i=1;i<=n;++i)
      {
             for(j=1;j<=n;++j)
           {
                  c[ i ][ j ]=0; //该步骤属于基本操作 运行次数:n的平方 次
                  for(k=1;k<=n;++k)
                  c[ i ][ j ]+=a[ i ][ k ]*b[ k ][ j ]; //该步骤属于基本操作 运行次数:n的三次方 次
           } 
      }
      则有 T(n)= n的平方+n的三次方。依据上面括号中的同数量级,我们能够确定 n的三次方 为T(n)的同数量级
      则有f(n)= n的三次方,然后依据T(n)/f(n)求极限可得到常数c
      则该算法的 时间复杂度:T(n)=O(n的三次方)
    [转]算法复杂度的计算
    算法复杂度是在《数据结构》这门课程的第一章里出现的。由于它略微涉及到一些数学问题,所以非常多同学感觉非常难,加上这个概念也不是那么详细。更让很多同学学起来无从下手,以下我们就这个问题给各位考生进行分析。

    首先了解一下几个概念。一个是时间复杂度,一个是渐近时间复杂度。前者是某个算法的时间耗费,它是该算法所求解问题规模n的函数,而后者是指当问题规模趋向无穷大时。该算法时间复杂度的数量级。
    当我们评价一个算法的时间性能时,主要标准就是算法的渐近时间复杂度,因此,在算法分析时,往往对两者不予区分,常常是将渐近时间复杂度T(n)=O(f(n))简称为时间复杂度。当中的f(n)通常是算法中频度最大的语句频度。

    此外,算法中语句的频度不仅与问题规模有关。还与输入实例中各元素的取值相关。

    可是我们总是考虑在最坏的情况下的时间复杂度。以保证算法的执行时间不会比它更长。

    常见的时间复杂度,按数量级递增排列依次为:常数阶O(1){Hash表的查找}、对数阶O(log2n){二分查找}、线性阶O(n)、线性对数阶O(nlog2n){高速排序的平均复杂度}、平方阶O(n^2){冒泡排序}、立方阶O(n^3){求最短路径的Floyd算法}、k次方阶O(n^k)、指数阶O(2^n){汉诺塔}。
    以下我们通过样例加以说明,让大家碰到问题时知道怎样去解决。
    1、设三个函数f,g,h分别为 f(n)=100n^3+n^2+1000 , g(n)=25n^3+5000n^2 , h(n)=n^1.5+5000nlgn 
    请推断下列关系是否成立:
    (1) f(n)=O(g(n)) 
    (2) g(n)=O(f(n)) 
    (3) h(n)=O(n^1.5)
    (4) h(n)=O(nlgn)
    这里我们复习一下渐近时间复杂度的表示法T(n)=O(f(n)),这里的"O"是数学符号,它的严格定义是"若T(n)和f(n)是定义在正整数集合上的 两个函数。则T(n)=O(f(n))表示存在正的常数C和n0 ,使得当n≥n0时都满足0≤T(n)≤C?

    f(n)。

    "用easy理解的话说就是这两个函数当整型自变量n趋向于无穷大时,两者的比值是一个不等于0的常 数。这么一来,就好计算了吧。

    (1)成立。题中因为两个函数的最高次项都是n^3,因此当n→∞时。两个函数的比值是一个常数,所以这个关系式是成立的。


    (2)成立。

    与上同理。
    (3)成立。

    与上同理。
    (4)不成立。因为当n→∞时n^1.5比nlgn递增的快,所以h(n)与nlgn的比值不是常数,故不成立。

    2、设n为正整数,利用大"O"记号。将下列程序段的运行时间表示为n的函数。
    (1) i=1; k=0 
    while(i<n)
    { k=k+10*i;i++;

    解答:T(n)=n-1。 T(n)=O(n), 这个函数是按线性阶递增的。
    (2) x=n; // n>1 
    while (x>=(y+1)*(y+1))
    y++;
    解答:T(n)=n1/2 。T(n)=O(n1/2)。 最坏的情况是y=0。那么循环的次数是n1/2次,这是一个按平方根阶递增的函数。
    (3) x=91; y=100; 
    while(y>0)
    if(x>100)
    {x=x-10;y--;}
    else x++;
    解答: T(n)=O(1)。 这个程序看起来有点吓人,总共循环执行了1000次,可是我们看到n没有? 没。这段程序的执行是和n无关的。就算它再循环一万年,我们也无论他,仅仅是一个常数阶的函数。
    规则:有例如以下复杂度关系
    c < log2N < n < n * Log2N < n^2 < n^3 < 2^n < 3^n < n!
    当中c是一个常量。假设一个算法的复杂度为c 、 log2N 、n 、 n*log2N ,那么这个算法时间效率比較高 ,假设是 2^n , 3^n ,n!,那么略微大一些的n就会令这个算法不能动了,居于中间的几个则差强人意。
    我们常须要描写叙述特定算法相对于 n(输入元素的个数 )须要做的工作量。在一组未排序的数据中检索,所需的时间与 n成正比。假设是对排序数据用二分检索,花费的时间正比于logn。排序时间可能正比于n^2或者nlogn。
    我们希望可以比較算法的执行时间和空间要求,并使这样的比較能与程序设计语言、编译系统、机器结构、处理器的速度及系统的负载等复杂因素无关。

    为了这个目的,人们提出了一种标准的记法。称为“大O记法”.在这样的描写叙述中使用的基本參数是 n,即问题实例的规模。把复杂性或执行时间表达为n的函数 。

    这里的“O”表示量级 (order)。比方说“二分检索是 O(logn)的”,也就是说它须要“通过logn量级的步骤去检索一个规模为n的数组”记法O ( f(n) )表示当n增大时,执行时间至多将以正比于f(n)的速度增长。这样的渐进预计对算法的理论分析和大致比較是很有价值的,但在实践中细节也可能造成差异。比如,一个低附加代价的O(n2)算法在n较小的情况下可能比一个高附加代价的O(nlogn)算法执行得更快。当然,随着n足够大以后,具有较慢上升函数的算法必定工作得更快。

    Temp=i;i=j;j=temp;                     以上三条单个语句的频度均为1。该程序段的运行时间是一个与问题规模n无关的常数。
    算法的时间复杂度为常数阶,记作T(n)=O(1)。假设算法的运行时 间不随着问题规模n的添加而增长。即使算法中有上千条语句,其运行时间也只是是一个较大的常数。此类算法的时间复杂度是O(1)。
     
    例 2.1. 交换i和j的内容
     

    1) sum=0;             (一次)
    2) for(i=1;i<=n;i++)   (n次 )
    3)    for(j=1;j<=n;j++) (n^2次 )
    4)         sum++;       (n^2次 )

    解:T(n)=2n^2+n+1 =O(n^2)
     
    例 2.2.
    for (i=1;i<n;i++)...{ y=y+1;        ① for (j=0;j<=(2*n);j++)    x++;           ②}          解:语句1的频度是n-1, 语句2的频度是(n-1)*(2n+1)=2n^2-n-1.
    f(n)=2n^2-n-1+(n-1)=2n^2-2,该程序的时间复杂度T(n)=O(n^2).
    例 2.3.
     

    a=0;b=1;      ①
    for (i=1;i<=n;i++) ②
    ...{
      s=a+b;    ③  
      b=a;     ④
      a=s;     ⑤
    }

    解:语句1的频度:2,        语句2的频度: n,        语句3的频度: n-1,        语句4的频度:n-1,    
    语句5的频度:n-1,                                  则:T(n)=2+n+3(n-1)=4n-1=O(n).
     
    例 2.4.
     
    i=1;       ①
    while (i<=n)
    i=i*2; ②
    解:语句1的频度是1,        设语句2的频度是f(n),        则:2^f(n)<=n;f(n)<=log2n    
    取最大值f(n)= log2n,则该程序的时间复杂度T(n)=O(log2n )
     
    例 2.5.
    for(i=0;i<n;i++)...{  for(j=0;j<i;j++)  ...{    for(k=0;k<j;k++)      x=x+2;  }}解:当i=m, j=k的时候,内层循环的次数为k当i=m时, j 能够取 0,1,...,m-1 ,  所以这里最内循环共进行了0+1+...+m-1=(m-1)m/2次所以,i从0取到n, 则循环共进行了: 0+(1-1)*1/2+...+(n-1)n/2=n(n+1)(n-1)/6所以时间复杂度为O(n^3).我们还应该区分算法的最坏情况的行为和期望行为。如高速排序的最坏情况执行时间是O(n^2)。但期望时间是O(nlogn)。

    通过每次都细致地选择基准值。我们有可能把平方情况 (即O(n^2)情况)的概率减小到差点儿等于0。在实际中,精心实现的高速排序一般都能以(O(nlogn)时间执行。

    以下是一些经常使用的记法:
    訪问数组中的元素是常数时间操作,或说O(1)操作。一个算法假设能在每一个步骤去掉一半数据元素,如二分检索,通常它就取O(logn)时间。用strcmp比較两个具有n个字符的串须要O(n)时间 。常规的矩阵乘算法是O(n^3),由于算出每一个元素都须要将n对元素相乘并加到一起。全部元素的个数是n^2。
    指数时间算法通常来源于须要求出全部可能结果。比如,n个元 素的集合共同拥有2n个子集,所以要求出全部子集的算法将是O(2n)的。指数算法一般说来是太复杂了,除非n的值很小,由于,在这个问题中添加一个元素就导致执行时间加倍。不幸的是。确实有很多问题 (如著名 的“巡回售货员问题”),到眼下为止找到的算法都是指数的。

    假设我们真的遇到这样案件, 它通常应被用来查找附近似最好的选择算法的结果。

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    flash中网页跳转总结
    as3自定义事件
    mouseChildren启示
    flash拖动条移出flash无法拖动
    需要一个策略文件,但在加载此媒体时未设置checkPolicyFile标志
    Teach Yourself SQL in 10 Minutes
    电子书本地转换软件 Calibre
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes – Page 31 练习
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4660960.html
Copyright © 2011-2022 走看看