算法是处理问题的步骤(就像错菜的菜谱)


算法的时间复杂度 和空间复杂度合成为算法的复杂度



时间复杂度

首先 提到一个 时间频度 T(n),一个算法中语句的执行次数 称为时间频度 也叫 语句频度 。 一个算法执行所耗费的时间,理论上说是能算出来的,必须上级测试才可以得到,但是没必要对所有个的算法都上机测试,我们只要知道哪个算法耗费的时间多,哪个算法耗费的时间少就可以了。在一个算法中,算法花费的时间与算法中语句的执行次数成正比,哪个算法中语句的执行次数多,那么他耗费的时间就多。


在刚才提到 T(n) 中,n 称为问题的规模,当 n 变化的时候 ,T(n) 也不断变化。 他的变化规律就是就是时间复杂度。

一般情况下,算法中基本操作重复执行的次数是问题规模的某个函数,用T(n) 表示。若用某个辅助函数

f(n) ,使n趋近与无限大的时候, T(n) /f(n)  的极限值 为不等于0的常数,则称 f(n) 是 T(n) 的同数量级函数。 记作  T(n)=O(f(n))  ,  称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度 。


O(f(n)) 也叫大O记法,“O” 表示数量级,用来告诉你一个算法耗费的时间长度和处理出巨量大小的关系。他只是一个概念性记号,不能通过他来真正计算一个算法耗费的精确时长。

 

时间频度不同,但时间复杂度可能相同。如:T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。


不同的算法中,如果算法中语句的执行次数是可控的,即执行次数是一个常数,则时间复杂度为 O(1)。


常见的时间复杂度有:常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),…, k次方阶O(nk),指数阶O(2n)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。


我们在讨论时间复杂度的时候, 如果不做特别说明,那么我们一般认为讨论的是最坏情况下的时间复杂度——最坏时间复杂度。那么 为什么我讨论的是最坏时间复杂度呢? 原因是:在最坏情况下,时间复杂度是算法运行时间的上限,这样就保证了算法的运行时间不会比这个时间更长。

在最坏情况下,时间复杂度 T(n)=0(n)  表示对于任何输入实例,算法的运行时间 不可能大于 0(n) 。


还有一个平均时间复杂度,指所有可能的输入实例 均以等概率出现的情况下,算法的期望时间。


最坏时间复杂度和平均时间复杂度

最坏情况下的时间复杂度称最坏时间复杂度。一般不特别说明,讨论的时间复杂度均是最坏情况下的时间复杂度。 这样做的原因是:最坏情况下的时间复杂度是算法在任何输入实例上运行时间的上界,这就保证了算法的运行时间不会比任何更长。


在最坏情况下的时间复杂度为T(n)=0(n),它表示对于任何输入实例,该算法的运行时间不可能大于0(n)。 平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。
指数阶0(2n),显然,时间复杂度为指数阶0(2n)的算法效率极低,当n值稍大时就无法应用。




计算时间复杂度

例:

设 有一个长度为 n 的序列 lst,从其中找到 给定的值 k 的算法 大概如下:

lst = [a1,a2,......,an]

n = len(lst)

i=1

while i<=n  and lst[i] != k 

    i += 1   # 标记语句01

print( i )


在这个算法中,如果序列中不存在与 k 相等的值 ,那么 标记语句01 的执行频度为 f(n)=n ;

如果 序列中最后一个元素 等于 k ,那么  标记语句01 的频度 f(n) 的值 是常数 0




用时间复杂度来评价算法的性能


现有 算法 A  和算法 B  两个算法 来解决同一个问题;

算法A 的时间复杂度是     T(n)=100n2

算法B 的时间复杂度是     T(n)=5n3

在使用这两个算法解决问题的时候,

 如果 n<20  , 那么 算法B 的花费时间较少 ;当 n=19   时

            算法A的时间为 100*19**2 = 36100 

            算法B的时间为   5*19**3   = 34295

 如果 n>20 ,  那么 算法A 的花费时间较少 ;当 n= 21 时

            算法A的时间为 100*21**2 = 44100 

            算法B的时间为   5*21**3   = 46305


两个算法的渐近时间复杂度 分别是 O(n2)和O(n3)   在宏观 上表示了两个算法在时间复杂度上的质量。

在进行算法分析的时候,一般对 不区分最坏时间复杂度和渐进时间复杂度。



空间复杂度

空间复杂度 是对一个算法在运行过程中 占用存储空间大小 的度量。记作S(n) ,定义为 :该算法所消耗的存储空间, 是问题规模 n 的函数。 渐近空间复杂度 也常简称为空间复杂度。S(n)=O(g(n)) 。

可以简单的理解为算法在执行过程中消耗的资源。

一般包含一下几个方面:

存储算法所 使用的 存储空间

        算法 输入/输出 所使用的空间    (由需要解决问题的规模来决定, 不随算法的改变而改变)

        算法运行过程中临时占用的空间   (随算法的不同而不同)

        算法自身所占用的存储空间         (算法的书写长度来决定)

其中 当 算法运行过程中临时占用的空间 不随问题规模的大小而改变的,我们称这种算法 就地 进行 , 是节省存储的算法。

当算法的空间复杂度为一个常量,即不随被处理的数据量大小而改变的时候,可表示为O(1)