一、算法时间复杂度的定义
在进行算法分析时u,语句的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定的T(n)的数量级。算法的时间复杂度也称算法的时间量度。记作T(n)=O(f(n))。
这样用大写O来体现的时间复杂度记法叫做大 O记法。
一般情况下,随着n的增大,T(n)增长最慢的算法称为最优算法。
二、推导大O阶的方法
1.用常数1取代运行时间中的所有加法常数
2.在修改后的运行次数函数中,只保留最高阶项
3.如果最高项存在且不是1,则去除与这个项相乘的常数。
三、常见的时间复杂度
常见的时间复杂度所耗费时间从小到大依次是:
O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O (n3)
其中经常用的有O(1),O(logn),O(n),O(n2)。它们也有一些非官方的名称,O(1) 叫做常数阶、O(logn)叫做对数阶、O(n)叫做线性阶、O(n2)叫做平方阶。
1.常数阶
int sum = 0; int n = 100;
sum = (1 + n) * n / 2;
printf("%d", sum);
这个算法的执行次数是3次。根据推导大O阶的方法得这个算法的时间复杂度为O(1)。
无论n为多少,上述代码只执行三次,与问题的大小无关(n的多少),执行时间恒定的算法,我们称之为常数阶O(1).
2.线性阶
线性阶的循环结构会复杂很多,要确定某个算法的阶层,我们常常需要知道特定语句或某个语句集的运行次数。
int i; int n;
for (i = 0; i < n; i++) {
//时间复杂度为1的程序步骤序列
}
由于循环体运行的次数是n次,所以它的时间复杂度是O(n).
3.对数阶
下面这段代码的时间复杂度又是多少呢?
int count=1;
while(count<n){
count=count*2;
//时间复杂度为1的程序步骤序列
}
由于每次count*2之后,就距离n更近一分,也就是说2^x>n就会退出循环。可得x=log2n。所以这个循环的时间复杂度是O(logn)。
4.平方阶
对于一个嵌套循环来讲,它的时间复杂度又应该怎么分析?
int i,j;
for(i=0;i<n;i++)
{for(j=0;j<n;j++)
{//时间复杂度为1的程序步骤序列}
}
它的内层循环已经分析过,它的时间复杂度是O(n)。它的外层循环,相当于内部时间复杂度为O(n)的语句再循环执行n次。所以它的时间复杂度是O(n2)。
四、空间复杂度
空间复杂度也是一个数学表达式,用来衡量算法运行时临时占用的存储空间量。
空间的复杂度不是程序占用空间的多少,因为无意义,所以空间的复杂度是变量的个数。计算空间复杂度的规则与时间复杂度基本相似,同样使用大O阶表示法。
注意:堆栈空间(存储参数、局部变量、注册表信息等。)是执行函数所必需的。)是在编译时确定的,所以空间的复杂度主要由函数在运行时显式申请的额外空间决定。