介绍
作为一个计算机自学的初学者,看了不少中文的时间复杂度入门,一直看不太懂,之后在日本的qiita上看到了这篇文章
[初心者向け] プログラムの計算量を求める方法
非常简单易懂,于是自己总结并且简单搬运一下。
同样是按照原文说的,因为是面向初学者,所以比起严密,易于理解更加重要。
关于代码
原文使用c语言(c99)写的,我在这里为了初学者而使用python。
什么是复杂度
在日文中时间复杂度叫时间计算量,复杂度就是
一个程序有怎样的速度的粗略表示的指标
稍微正确的说就是
输入大小的增加,到底执行时间以怎样比例增加的指标
通过图像来看计算量
在这里,输入数据按照n增加,执行时间也是按照n来增加。
现在来看看别的图片。
输入数据按照n增加,但实行时间是按照n的平方增加。
计算量有啥用
计算量可以比较两个算法的性能,很简单的看上图,蓝色的曲线性能要更加优越,同样的输入大小下运算时间更少。
大O记法表示计算量
计算量一般采用O记法,比如上面的例子就可以写成O(n)和O(n^2)。
如何求计算量
def calculate(n):
count = 0
for i in range(n):
count = count + 1
for i in range(n):
for j in range(n):
count = count + 1
for i in range(n):
for j in range(n):
count = count + 1
return count
复杂度按照以下三个步骤求出来
第一步)求出各行的执行次数
def calculate(n):
count = 0 ##执行1次
for i in range(n):
count = count + 1 ##执行n次
for i in range(n):
for j in range(n):
count = count + 1 ##执行n^2次
for i in range(n):
for j in range(n):
count = count + 1 ##执行n^2次
return count ##执行1次
第二步)求出程序全部的步数
将各行步数相加,求出程序总的步数。
程序全体的步数 = 1+n+n2+n2+1
=2+n+2n^2
第三步)将不需要的东西扔掉
把上面求出的总步数中不要的东西扔掉
a.把最高次以外的项省略
2+n+2n^2 --> 2n^2
b.把系数省略
2n^2 --> n^2
结果
最终这个程序的复杂度就是
O(n^2)
求复杂度时的规则
在求复杂度时要注意以下规则
规则1)将最高次以外的省略
在求复杂度时将低次项省略,只保留最高次。
理由)
求复杂度是在输入大小非常大的前提下去考虑的,所以输入非常大时,低次项的重要度就变得相当的低,于是可以无视。
比如,输入n很小的时候( n = 10 )
n^2 + n = 110
n^2 = 100
这个时候低次项影响较大,但如果输入很大的话 ( n = 100000 )
n^2 + n = 10000100000
n^2 = 10000000000
这样看低次项的重要性就很小了。
规则2)系数省略
在复杂度的定义上,常数倍的不同是可以省略的。比如,O(n),O(2n),O(3n)之间只有互为常数倍的不同,系数部分无视,哪一个的复杂度都是O(n)。
例子
顺序执行
- 代码
count = count + 1 ##执行一次
count = count + 1 ##执行一次
-
总次数
命令按照顺序执行,总次数相加就是两次 -
复杂度
上面的代码不会按照输入什么而不同,所以复杂度写出来就是
O(1)
循环
- 代码
for i in range(n/3):
count = count + 1 ##执行n/3次
-
总次数
n/3 -
复杂度
因为和常数倍数无关,所以省略系数
n/3 --> O(n)
循环
- 代码
for i in range(n)
i = i * 2
count = count + 1 ##执行log(n)次
-
总次数
执行一次后 i 乘以2,一直到n,类似二分法的执行次数,所以是log(n)次,注意在信息学中log的底通常为2。 -
计算量
O(log n)
结尾
翻译就到这里,其他的部分很多是在重复,会日语的朋友可以自己去看看,基本是我见过的最简单的关于时间复杂度的入门文章,有兴趣的朋友可以再参考其他的文章。顺便说一个,在做MIT算法公开课的题目是看到这句话
log n is O(n^c)
这里注意一下,在我的理解中,等于不是等于的意思,而是是的意思。大O只是一种符号去表达一个渐进的上边界的意思,类似于极限的概念,在考虑问题时不要搞混
上面的等于来源于这条规则。
一篇文章就不讲太多了,希望大家好好学习天天向上。