时间复杂度
时间复杂度一直很迷。。。。 在网上找了看了一些博客,一句话,看不懂。。。。 于是自己去学了一下,总结为下面的。
算法的效率,就是说一个算法的执行时间,它始终还是由我们执行每一行代码的次数来决定。我们可为每一个算法编写一个测试程序,然后拿到机器上去跑,但是由于除了算法本生,测试结果还受到很多其他因素的影响,列如cpu
的执行速度等不确定因素,而且我们也不可能为了每一个算法去编写一个测试程序这样也不现实。
所以后来人们采用事前估算的方法,依据统计学。这种情况下抛开了其他所有的不确定因素,一个算法的效率由一个算法的本生好坏和输入规模来决定。
例如:
当n
很大的时候,两种算法的差距就大了起来,第一个是2n+2
次,第二个始终都是2
次。
上面的两个算法分别可以看做时间复杂度为n
和1
,下面来解释为什么是这样。
时间复杂度
研究算法的复杂度,侧重的研究输入规模很大的情况,在这种情况下我们就可以忽略一个复杂度中的一些小项,也就是执行次数特别大的情况,因为这样才能判定一个算法的在某种场景下的好与坏,这个时候就需要利用统计学知识。我们接下来通过大量的例子来解释。通过这几个例子为后面的算法时间复杂度做铺垫。
例一
将设A
算法要做2n+3
次计算,B
需要做3n+1
次操作,你觉得哪一个更快一点呢。下面来看看统计的结果。
从结果来看最开始算法A1
不及B1
,当n
大于5
的时候,执行次数少于B1
,到后面完全胜过它,这就是输入规模的重要性,而且我们看A2、B2
发现当输入规模很大的时候常数项可以完全忽略。
函数的渐进增长: 给定两个函数,f(n)、g(n)
,如果存在一个整数n
当n>N
的时候,f(n)
总是比g(n)
大,那么我们说f(n)
的渐进增长比g(n)
大。
当
例二
算法C
为4n+8
,算法D
为2n^2 + 8
图上有错,第二张图为C1、C2, D1,D2
。
从观察当中可以可以发现,当n
很大的时候,相乘的系数,影响也很小了,比如4n+8和n
,在图上都重叠到一块儿去了,但是对于C1、C2
,系数有影响,但是对比C、D
算法的时候,可以看出系数并不影响比较。可以得出结论系数不影响两个算法之间的比较,因此也可以去掉。
例三
算法E
为2n^2+3n+1
,算法F
为2n^3+3n+1
通过图中对比E、F
两个算法,可以看到指数对于测试结果影响很大。
例四
算法G
为2n^2
,算法H
为3n+1
,算法I
为2n^2+3n+1
因此我们可以得出结论: 判断一个算法的效率的时候,函数中的常数和次要项都可以忽略,而更应改关注最高项的介数。
时间复杂度的计算
用大写O()
来作为时间复杂度的记法,称为大O
记法
那么我们怎么来推导大O
阶呢。首先我们需要计算出程序执行的次数,再按照下面总结出来的方式来求解,这里的总结均来自前面的例子
- 只有常数项,将常数看做
1
,得到O(1)
- 对于多项表达式,只保留最高项,且去除与这个项相乘的常数
其实就是这么简单。。。。,我在网上看到的其他文章语言实在太官方,明明简单的东西被这些糟老头子给整复杂了。下面来看几个计算的例子:
上面的时间复杂度为O(1)
时间复杂度为O(n)
时间复杂度为o(n^2)
上面的例子为对数阶。假设程序执行x
次退出循环,那么可以得到等式2^x=n
,所以当x=log(2底数)n
的时候推出循环,执行次数为log(2)n + 1
,所以可以得到最终结果为O(logn)
还有一个空间复杂度,空间可以换取时间,时间也可以换取空间,在实际当中往往要在二者之间达到一个平衡