【前言】
从一开始接触数据结构的时候,就对时间复杂度了解不清晰,后来的多次考试中都有接触,但还是感觉没有把握时间复杂度的要点所在。最近学习考研专业课,又一次碰上了时间复杂度,感觉这次学习还是有了收获和进步,特此总结下来,希望对读者有帮助。【如何计算算法的时间复杂度】
小编把对算法时间复杂度计算的分析过程梳理了一下,我们来一步步走进时间复杂度吧!1.时间复杂度的含义
首先我们需要明确时间复杂度的含义,时间复杂度是什么呢?是执行完一段程序所花费的总时间么?答案是否定的,时间复杂度最后的度量单位并不是时间,我们把算法中基本操作的执行次数作为算法时间复杂度的度量,所以时间复杂度就是算法基本操作的总次数。
所以,我们现在明确了时间复杂度的含义,了解到对算法进行时间复杂度分析的要点,就是明确算法中哪些操作属于基本操作,然后计算出基本操作重复执行的次数就OK了。
但其中又提到了一个新的名词——基本操作执行次数,那什么又是基本操作呢?
2.基本操作的含义
基本操作就是以求时间复杂度为目的的前提下,重复执行次数和算法的执行时间成正比的操作。简单来说,基本操作组成了算法,当基本操作都执行完毕的时候,算法也就结束了。多数情况下,我们会取算法中最深层循环内的语句所描述的操作为基本操作。(下面会有举例说明)
3.计算基本操作执行次数
计算基本操作的执行次数,还要有一个概念辅助它,就是问题规模。在算法题目中,我们总能找到一个n,称这个n为问题规模。比如要处理的数组元素个数为n个,而基本操作所执行的次数就是关于问题规模 n 的一个函数f(n),我们要求的基本操作的次数,就是去求函数f(n)。4.计算时间复杂度
我们求出函数f(n)之后,取出f(n)中随n增大而增长最快的的项,然后将其系数变为1。将增长最快的项系数化为1后的结果,作为时间复杂度的度量,
记为 T(n)= O( f(n)函数中增长最快的项 / 此项的系数)
例如 f(n)=5n³ +5n² +220,则其时间复杂度计算为 T(n)=O(5n³/5)=O(n³)
通过上面的计算我们得知,计算算法的时间复杂度就是给出相应的数量级.
当f(n)和n没有关系的时候,时间复杂度就是T(n)=O(1)。当f(n)和n为线性关系的时候,T(n)=O(n)。当f(n)和n为二次方关系的时候,T(n)=O(n²),以此类推~
5.计算时间复杂度步骤总结:
第一步:确定算法中的基本操作以及问题规模。第二步:根据基本操作执行情况,计算出规模n的函数f(n),
并确定时间复杂度为T(n)= O( f(n)函数中增长最快的项 / 此项的系数)
PS:需要提醒大家的是,有些算法中基本操作的执行次数不仅跟初始输入的数据规模有关,还和数据本身有关。例如一些排序算法,同样都是n个待处理数据,但是数据初始的有序性不同,则基本操作的执行次数也不同。所以我们都依照使得基本操作执行次数最多的输入来计算时间复杂度,就是将最坏的情况作为算法时间复杂度的度量。
6.举个栗子
我们来计算一下时间复杂度void fun(int n) { int i=1,j=100; While(i<n) { ++j; i+=2; } }
第一步,我们要找出算法中的基本操作和问题规模n。
基本操作就去找最深层循环内的语句,就是++j; i+=2; ,这两行都可以作为基本操作。看到循环条件 i<n,我们知道循环执行的次数也就是基本操作执行的次数,和这个参数n有关,这个参数n就是我们说的问题规模n。第二步:计算出关于n的函数f(n)。
我们已经确定了问题规模为n,再看算法的循环语句,这个循环什么时候会结束呢,i<n的时候会一直执行基本操作语句,也就是当i不再小于n的时候,循环才会结束。所以基本操作执行次数,还和i这个参数有关系。
由 i=1;我们得知i的初值为1,由 i+=2; 我们得知i每次自增2。我们现在得假设一下,因为我们要算出时间复杂度啊,需要知道i自增多少次才结束循环,我们假设i在自增m次()之后结束了循环,大家思考下,这个m次,是不是就是我们要求的基本操作执行次数呢。所以i最后的值是 i=1+2m 。
这时有 1+2m+K=n (这个K又是什么意思呢?K是一个常数,因为我们前面已经知道,当i不再小于n的时候,循环才会结束,所以最后i的值会稍微大于n的,为了方便表述和计算,我们用K来将1+2m 修正为n,因为K是个常数,是不会影响到最后的时间复杂度计算的)。
这时我们来计算m的值,m=(n-1-K)/2,即f(n)=(n-1-K)/2,我们发现其中增长最快的项是 n/2,将此项系数化为1,计算得时间复杂度为T(n)=O(n)。当当当,时间复杂度就计算出来啦,这只是一个比较简单的小例子,对于时间复杂度的计算还需要我们加强训练啊~