前言:算法效率分析的目的是在算法实际可行的基础上进行时间和空间性能上的比较,算法时间效率越高、存储量越低则算法越优秀。本文主要围绕时间复杂度这一概念展开叙述。
一、何为时间复杂度
前置概念:
- 语句频度:单条语句的重复执行次数。
- 算法执行时间:算法执行时间为算法中所有语句频度之和。
- 问题规模:算法求解问题输入量的多少,是问题大小的本质,一般用n表示。n越大,算法执行时间越长。
- 基本语句:算法中重复执行次数和算法的执行时间成正比的语句。
由此可知,问题规模决定算法执行时间,算法的问题规模越大,则语句频度随之递增,算法执行时间越长,因此可以引出时间复杂度这一概念。
官方解释为,随着问题规模n的增大,算法执行时间的增长率和某个函数的增长率相同,就称作为算法的渐进时间复杂度,简称为时间复杂度。可以简单理解为算法运行时所消耗的时间。时间复杂度用O表示。
二、算法时间复杂度分析
问题规模不同的函数都有着不同的时间复杂度,因此总结出以下定理,当遇到未见过的函数时结合定理进行判断即可快速计算时间复杂度。
- 定理一:用常数1取代运行时间中的所有加法常数(原因在于时间不随n增加)。
- 定理二:在修改后的运行次数函数中,只保留最高项(使用语句频度最大的那条语句作为基本语句计算时间复杂度)。
- 定理三:如果最高项存在且不是1,则除以与这数相乘的常数(甩掉常数)。
以下列举常见函数的时间复杂度。
1.常数阶
常数阶即问题规模为常数的函数,类似如:
1 for(i=0;i<10000;i++){
2 x++;
3 s=0;
4 }
可见上述案例的问题规模为10000,但是根据定理一可知,问题规模为常数,时间复杂度不管多大都为1,因此时间复杂度为O(1)。
2.线性阶
以下为线性阶示例:
1 for(i=0;i<n;i++){
2 x++;
3 s=0;
4 }
上述示例问题规模为n且两条基本语句的频度均为f(n)=n,所以时间复杂度为O(n)。
3.平方阶
平方阶示例:
1 x=0;y=0;
2 for(k=1;k<=n;k++){
3 x++;
4 }
5 for(i=1;i<=n;i++){
6 for(j=1;j<=n;j++){
7 y++
8 }
9 }
显然,上述示例中频度最大的语句为第七行的y++,因此根据定理二,我们选择y++作为基础语句,又因为y++这一语句执行次数为n^2次,因此可知时间复杂度为O(n^2)。
4.对数阶
对数阶示例:
1 for(i=1;i<=n;i=i*2){
2 x++;
3 s=0;
4 }
由上述示例可得等式2^f(n)<=n 换算=> f(n)<=log(2)n 因此对数阶时间复杂度为O(log(2)n)。
常用的时间复杂度大小排序:
O(1)<O(log(2)n)<O(n)<O(nlog(2)n)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^2)
三、最好、最坏、平均时间复杂度
- 最好时间复杂度:指的是算法计算量可能达到的最小值。
- 最坏时间复杂度:指的是算法计算量可能达到的最大值。
- 平均时间复杂度:指算法在左右可能情况下,按照输入实例以等概率出现时,算法计算量的加权平均值。
通常在实际计算算法时间复杂度时,都是计算的最坏时间复杂度。