在进行算法分析时,语句总是执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,基座:T(n)=O(f(n)).它表示岁问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。
这样用大写O( )来体现算法时间复杂度的激发,我们称之为大O记法。
一般情况下,随着n的增大,T(n)增长最慢的算法为最优算法。三个求和算法的时间复杂度分别为O(n),O(1),O(n^2).我们分别给他们取了非官方的名臣,O(1)叫常数阶、O(n)叫线性阶、O(n^2)叫平方阶。
推导大O阶:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项相乘的常数。得到的结果就是大O阶。
例如 :
常数阶:
这个算法的运行次数函数是f(n)=3.根据我们推导大O阶的方法,第一步就是把常数项3改为1.在保留最高阶项时发现,他根本没有最高阶项,所以这个算法的时间复杂度为O(1).
线性阶:
对数阶:
由于每次count乘以2之后,就距离n更近了一份,也就是说,有多少个2相乘后大于n,则会推出循环,由2^x=n 得到x=log2n.所以这个循环的时间复杂度为O(logn).
平方阶:
而对于外层的循环,不过是内部这个时间复杂度为O(n)的语句,再循环n次。所以这段代码的时间复杂度为O(n^2).
那么下面这个循环嵌套,它的时间复杂度是多少呢
由于当i=0时,内循环执行了n次,当i=1时,执行了n-1次,、、、当i=n-1时,执行了1次,所以总的执行次数为:
n+(n-1)+(n-2)+...+1=n(n+1)/2=n^2/2+n/2
用我们推导大O阶的方法,第一条,没有加法常数不予考虑;第二条,只保留最高阶项,因此保留n^2/2
;第三条,去除这个项相乘的常数 ,也就是去除1/2,最终这段代码的时间复杂度为O(n^2).
常见时间复杂度一览表:
常用时间复杂度所耗费的时间从大到小依次是:
最坏情况运行时间是一种保证,那就是运行时间将不会再坏了,在应用中,这是一种最重要的需求,通常,除非特别指定,我们提到的运行时间都是最坏情况的运行时间。
平均运行时间是所有情况中最有意义的,因为他是期望的运行时间。
算法的空间复杂度是通过计算算法所需的存储空间实现,算法时间复杂度的计算公式记作:s(n)=O(f(n)),其中,n为问题的规模,f(n)为语句关于n所占存储空间的函数。
一般情况下,一个程序在机器上执行时,除了需要存储程序本身的指令、常数
变量和输入数据外,还需要存储对数据操作的存储单元。若输入数据所占空间只取决于问题本身,和算法无关,这样只需要分析该算法在实现时所需的辅助单元即可。若算法执行时所需要的辅助空间相对于输入数据量而言是个常数,则称此算法为原地工作,空间复杂度为O(1).
通常,我们都使用“时间复杂度”来指运行时间的需求,使用“空间复杂度”指空间需求。当不用限定词地使用“复杂度”时,通常都是指时间复杂度。