度量程序效率的方法
- 事后统计:在程序运行之后,根据程序执行的时间对程序的性能进行评测,这种方法需要实际的运行该程序,并且时间的统计量依赖于计算机的硬件、软件等环境因素,使用这种方法需要在同一台计算机的相同状态下运行,才能比较哪个算法速度更快
- 事前估算:通过分析某个算法的时间复杂度来判断按个算法
时间频度
- 一个算法花费的时间和算法中语句的执行次数成正比,哪个算法语句执行次数多,花费的时间就多。算法中的语句执行次数成为语句频度和时间频度T(n)
- 随着n值的变大,常数项对函数的影响,即语句执行次数的影响越来越小,所以可以忽略常数项
- 随着n的变大,低次项对执行次数的影响越来越小,所以可以忽略低次项
- 随着n的变大,系数对n的影响越来越小,所以可以忽略系数
时间复杂度
- 一般情况下,算法中的基本操作语句的重复执行次数是问题规模n的某个函数T(n)(时间频度),使用一个辅助函数f(n),使得当n趋于无穷大时,T(n)/f(n)的极限值为不等于0的常数,则称f(n)是T(n)的同数量级函数,记作T(n)=O(f(n))称O(f(n))为算法的时间复杂度
- T(n)=n2+7n+6于T(n)=3n2+2n+2两个函数的T(n)不同,但是时间复杂度相同,都是O(n2)
常见的时间复杂度
- 常数阶:O(1)
- 对数阶:O(log2n)
- 线性阶:O(n)
- 线性对数阶:O(nlog2n)
- 平方阶:O(n2)
- 立方阶:O(n3)
- k次方阶:O(nk)
- 指数阶:O(2n)
常见的算法时间复杂度由小到大依次为:O(1)<O(log2n)<O(nlog2n)<O(n)<O(n2)<O(n3)<O(nk)<O(2n)
常数阶O(1)
int i=1;
int j=1;
int m=i+j;
无论代码执行了多少行,只要是没有循环等复杂结构,那么时间复杂度就是O(1),哪怕代码执行了几十万行,它的时间复杂度和只执行一行的代码都是O(1)
对数阶O(log2n)
int i=1;
while(i<n) {
i*=2;
}
在while循环中,每次i都会乘以2;当i等于n的时候,i乘了k次2,即2k=n,得出k=log2n
线性阶
for(int i=0;i<n;i++){
System.out.println(i);
}
这段代码一共会执行n遍,执行的次数和n呈线性关系
线性对数阶
for(int i=1;i<n;i++){
int j=1;
while(j<n){
j*=2;
}
}
在线性阶的循环中,每次都要执行依次对数阶复杂度的代码,最终的时间复杂度即两者相乘
平方阶
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
System.out.println(i);
}
}
在双重循环中,代码执行次数为n*n即n2,立方阶、k次方阶同理
平均时间复杂度和最坏时间复杂度
- 平均时间复杂度是指所有可能输入的实例以均等的概率出现的情况下,运行时间
- 最坏时间复杂度,是指使算法执行时间最长的一组实例的时间复杂度