导读
每个程序解决问题时都可能有不同的实现方法,也就是我们常说的算法,而不同的算法对计算机资源的占用都不一样,因此我们常用算法复杂度来衡量一个算法的优劣程度。
算法复杂度是对程序计算机资源占的度量,这些资源主要包括时间资源和内存资源,因此算法复杂度又分为时间复杂度(时间资源的度量)和空间复杂度(内存资源的度量)。
一、时间复杂度(Time Complexity)
算法的时间复杂度简单来说就是一个函数,它定性描述了该算法的运行时间。
我们知道一个程序的运行就是计算机内部的指令的执行,而每条指令执行的时间即指令周期大致相同,上升到程序中或者说算法上来,可以理解为每条语句执行的时间大致相同,所以只要计算出算法中基本语句的执行次数就能定性地对时间复杂度进行度量。我们一般将执行次数的总和记为函数f(n),n是指问题的规模。
例如下面的算法:
for(i=1; i<=n; ++i) { for(j=1; j<=n; ++j)//规模为n { c[i][j] = 0;//基本操作① for(k=1; k<=n; ++k) c[i][j] += a[i][k] * b[k][j];//基本操作② } }
上面的算法中有两条基本语句也就是要执行的基本操作,操作①的执行次数为:n^2,操作②的执行次数为:n^3,所以该算法的执行次数f(n) = n^2 + n^3。
其实函数f(n)就可以作为时间复杂度的计量函数,但我们通常使用T(n)=O(f(n))函数来代表时间复杂度。O(f(n))是取f(n)函数的最高次项(变化最快的项),再将系数化为1。即T(n) = O(f(n)) = O(n^3)。所以O(n^3)即为本例算法的时间复杂度。
综上:
时间复杂度的计算方法:
1)计算基本操作的执行次数f(n)。
2)将f(n)转换为T(n)=O(f(n))。
常见的时间复杂度的大小排序:(复杂度越小算法越优)
O(1) <= O(log2(n)) <= O(n) <= O(nlog2(n)) <= O(n^2) <= ... <= O(n^k) <= O(2^n)
时间复杂度相同级别时的比较:
当若干算法的时间复杂度级别相同时,我们可以考虑算法的数据输入状态,即除了指令的运行时间,数据的存储时间也是时间资源。
二、空间复杂度(Space Complexity)
算法的实现首先需要寄存器对数据和指令进行临时存储,这就需要占用到内存等资源,空间复杂度就是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)。
比如直接插入排序的时间复杂度是O(n^2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。
三、时间复杂度和空间复杂度的关系
百科:对于一个算法,其时间复杂度和空间复杂度往往是相互影响的。当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间;反之,当追求一个较好的空间复杂度时,可能会使时间复杂度的性能变差,即可能导致占用较长的运行时间。另外,算法的所有性能之间都存在着或多或少的相互影响。因此,当设计一个算法(特别是大型算法)时,要综合考虑算法的各项性能,算法的使用频率,算法处理的数据量的大小,算法描述语言的特性,算法运行的机器系统环境等各方面因素,才能够设计出比较好的算法。算法的时间复杂度和空间复杂度合称为算法的复杂度。