容易描述时间复杂度和空间复杂度(转)

简单描述时间复杂度和空间复杂度(转)
1、算法复杂度

  算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是度量算法执行的时间长短;而空间复杂度是度量算法所需存储空间的大小。
2
、时间复杂度
  1.
一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数fn),因此,算法的时间复杂度记做:Tn=Ofn))   
分析:随着模块n的增大,算法执行的时间的增长率和fn)的增长率成正比,所以fn)越小,算法的时间复杂度越低,算法的效率越高。
 2. 在计算时间复杂度的时候,先找出算法的基本操作,然后根据相应的各语句确定它的执行次数,再找出Tn)的同数量级(它的同数量级有以下:1Log2n n nLog2n n的平方,n的三次方,2n次方,n!),找出后,fn=该数量级,若T(n)/f(n)求极限可得到一常数c,则时间复杂度 Tn=Ofn))  
 例:算法:  

Java代码  容易描述时间复杂度和空间复杂度(转)

  1. fori=1;i<=n;++i   {   
  2.   for(j=1;j<=n;++j)      
  3.      c[ i ][ j ]=0//该步骤属于基本操作 执行次数:n的平方      
  4.       for(k=1;k<=n;++k)    
  5.        c[ i ][ j ]+=a[ i ][ k ]*b[ k ][ j ]; //该步骤属于基本操作 执行次数:n的三次方     
  6.      }    
  7.      
  8. }  


则有 Tn= n的平方+n的三次方,根据上面括号里的同数量级,我们可以确定 n的三次方 Tn)的同数量级   则有fn= n的三次方,然后根据Tn/fn)求极限可得到常数c   则该算法的 时间复杂度:Tn=On的三次方)
   3.
分类
  按数量级递增排列,常见的时间复杂度有:   常数阶O(1),对数阶O(log2n),线性阶O(n),   线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),...   k次方阶O(nk), 指数阶O(2n) 。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。

3
、空间复杂度
一般是指执行这个算法所需要的内存空间。 一个算法所占用的存储空间包括算法程序所占用的空间、输入的初始数据所占用的存储空间以及算法执行过程中所需要的额外空间。一个程序的空间复杂度是指运行 完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指 令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。
1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。
S(n)=O(f(n))
其中n为问题的规模,S(n)表示空间复杂度。
4
、说明例子
时间复杂度描述一个算法对数据规模和执行时间之间的关系。
一个算法,处理n条数据需要的时间可以用表达式:a*n+b来表示的话,称它的时间复杂度为O(n),也就是说,100条数据需要1秒的话,1000条数 据需要10s。如果是用表达式:a*n*n+b*n+c的话,复杂度为O(n的平方),这样1001秒,1000条就要100s了。0(0)表达式为 a*(n0次方)+b,也就是个常数。这样无论100还是1000条都只需1秒。

空间复杂度类似,只是描述的是规模与存储空间的关系。下面来看个O(n)O(1)的例子:
要从0加到n,我们会这么写:

Java代码  容易描述时间复杂度和空间复杂度(转)

  1. int sum = 0;  
  2. for(int i = 0; i<=n; ++i)  
  3. {  
  4.    sum += i;  
  5. }  


一共算了n次加法,那么就说这个时间复杂度是O(n)。当然O(n)的精确的概念是,是n的最高次方,比如,某个计算共计算了3n + 2次,那么这个时间复杂度也是O(n),因为3n + 2中的最高次方是n。分析如下代码:

Java代码  容易描述时间复杂度和空间复杂度(转)

  1. int sum = 0;  
  2. for(int i = 0; i<=n; ++i)  
  3. {  
  4.    for(int j = 0; j <=n; ++j)  
  5.    {  
  6.       sum += (i + j);  
  7.    }  
  8. }  



很显然一共算了n^2次加法,那么就说这个时间复杂度是O(n^2),和上面类似,如果某个算法计算了3*n^2 + n + 1次,其时间复杂度仍然是O(n^2),因为3*n^2 + n + 1中最高的次方是n^2

所谓O(1)就是计算的次数是个常量,我们还以上面从0加到n的例子来说,如果我们用等差数列的公式,那么,代码可以这么写:
int sum = n * (n + 1) / 2
不管n有多大(当然不能溢出了),通过上面的公式只需计算一次,也就说计算的次数是不变的,这种情况的时间复杂度就可以说成O(1) 再比如如果某个计算,不管其他条件怎么变化,均只需计算5次即可得出结果,那么这种情况的时间复杂度,也是O(1)

5
、复杂度判定
要在 hash 表中找到一个元素就是 O(1)
要在无序数组中找到一个元素就是 O(n)

访问数组的第 n 个元素是 O(1)
访问链表的第 n 个元素是 O(n)

简单的判断方法:
如果实现中没有循环就是 O(1)
如果实现中有一个循环就是 O(n)