关于算法的时间复杂度和空间复杂度

  • Post author:
  • Post category:其他



一:时间复杂度


一:概念

算法的时间复杂度是指

算法的执行时间是通过该算法编写的程序在计算机上执行时所需要的时间来计算的

,通常有以下两种方法:

(1)事后统计法:在计算机中执行程序以计算该算法的执行时间,但此时间会因为编程语言或计算机的硬件软件的不同而得出不一样的结果,因此很少使用。

(2)事前分析估算法:通常程序在计算机上运行时小号的时间取决于下列因素:①算法选用何种策略。②问题的规模。③所使用的程序设计语言,就同一个算法而言,用级别越高的语言实现,其执行效率越低。④编译程序所产生的机器代码的质量。⑤机器执行指令的速度。

由此不难看出,

采用绝对的时间单位来衡量一个算法的效率时不合理的

,因此我们应该撇开所使用的编程语言、计算机的硬件和软件等环境因素,仅仅考虑算法本身效率的高低。即认为某一算法的执行时间只依赖于问题的规模,或者说是问题规模的函数。


二:具体原理


通常来说:

一个算法是由

控制结构

(顺序、分支和循环3种)和

原操作

(指固有数据类型的操作)构成的。例如:

def Function(list):
    for i in range(0,len(list)):
        list[i] = 3*i        ##原操作
    for i in range(0,len(list)):
        print(list[i])       ##原操作    
    print("")                ##原操作

因此算法的执行之间取决于控制结构和原操作的综合效果。为了便于算法执行时间的计算,我们从算法中选取一种对于所研究的问题来说时基本操作的原操作,并以该操作重复执行的次数来计算其执行时间。


*

假设问题规模为n,对于的函数关系记为T(n),则算法的执行时间大致等于执行基本操作所示的时间乘以T(n)。通常执行基本操作所需的时间是某个确定的值,因此T(n)与算法的执行时间成正比,那么我们通过比较不同算法的T(n)大小,就可以得出不同算法的优劣。由下列例子为例,给出求解T(n)的过程:

##矩阵相加的函数
1:def Function(a,b,c,n):
2:    for i in range(0,n):
3:       for j in range(0,n):
4:           c[i][j] = a[i][j] + b[i][j]

上述代码中第2~4行为该算法的可执行语句。第2行代码中的i从0变化到n,因此重复次数是n+1次,但对应的循环体只执行了n次;同理第3行代码本身重复的次数也为n+1次,对应的循环体只执行了n次,但由于其嵌套在第2行代码内,因此第3行代码共重复了n*(n+1)次,同理第4行的代码重复的次数为
n^{_{_{_{2}}}}

综上所述,该算法的T(n)可用下式表示:T(n)=n+1+n(n+1)+
n^{_{_{_{2}}}}
=2
n^{_{_{_{2}}}}
+2n+1 。由于上述对算法执行时间的计算并不是该算法执行的绝对时间,因此通常进一步将算法的执行时间用T(n)的数量级来表示,

记作T(n)=O(f(n))

,其中O是数量级Order的缩写。具体含义是存在着正常量c和N(N为一个足够大的正整数),使得
\lim_{n-N}\frac{|T(n)|}{f(n)}=c
(c不等于0)成立。由该等式可以看出当n足够大时,T(n)和f(n)的增长率是相同的,因此我们将O(f(n))成为算法的渐进时间复杂度,简称算法的复杂度。

与T(n)对应的f(n)可能有多个,通常只求出T(n)的最高阶,忽略其低阶项、系数及常数项。如对于 T(n)=n+1+n(n+1)+
n^{_{_{_{2}}}}
=2
n^{_{_{_{2}}}}
+2n+1=O(
n^{_{_{_{2}}}}
),即上述算法的时间复杂度为O(
n^{_{_{_{2}}}}
).


三:几种常见判断时间复杂度


(1):算法中无循环

def fun(x,n):
    for i in range(0,n):
        x = x+1 

该算法中无循环,因此该算法的时间复杂度为O(1),称为常量阶。


(2):算法中含有一个单重循环

def fun(x,n):
    for i in range(0,n):
        x=x+1

该算法中变量i从0变化到n,基本操作执行了n次,因此该算法的时间复杂度为O(n),称为线性阶。


(3):算法中含有多重循环

def fun(x,n):
    for i in range(0,n):
        for j in range(0,n):
            x = x+1

该算法中有双重循环,外循环变量i从0变化到n,内循环变量j从0变化到n,因此基本操作执行了

n^{_{_{_{2}}}}

次,即该算法的时间复杂度为O(
n^{_{_{_{2}}}}
) ,称为平方阶。


四:小结

(1):时间复杂度是用来估算算法运行时间的一个式子(单位)

(2):一般来说,时间复杂度高的算法比复杂度低的算法慢

(3):常见的时间复杂度:O(1)<O(logn)<O(n)<O(nlogn)<O(
n^{_{_{_{2}}}}
)<O(
n^{_{_{_{2}}}}
logn)<O(
n^{3}
)

(4):复杂问题的时间复杂度:O(n!),O(
2^{n}
),O(
n^{n}
)


二:空间复杂度


与算法的时间复杂度类似,算法的空间复杂度一般也认为是问题规模n的函数,并以数量级的形式给出,记作S(n)=O(g(n)),用来评估算法内存占用大小的式子。

根据某算法编写的程序在计算机运行时所占用的存储空间包括以下部分:输入数据所占用的存储空间,程序本身所占用的存储空间和临时变量所占用的存储空间。在对算法的空间复杂度进行研究时,只分析临时变量所占用的存储空间。例如:

def sum(self,list):
    sum = 0
    for i in range(0,len(list)):
        sum = sum + list[i]
       return sum

算法1

在该算法中不计形参list所占用的空间,而只是计算临时变量i和sum所占用的存储空间,因此该算法的空间复杂度为O(1)。

def fun(self,list):
    list = [1,2,3,4,5,6,7,8,9]
    print("sum=",self.sum(list))

算法2

在算法中为列表list分配存储空间,而在第三行代码中调用了算法1中的sum()函数,若在算法1中再次考虑形参list占用的存储空间,则就重复计算了其占用的存储空间。

综上所述,在对算法的空间复杂度进行分析时,只需考虑临时变量所占用的存储空间而不用考虑形参占用的存储空间。



版权声明:本文为m0_52406329原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。