在算法分析中,将这个问题进行简化,不考虑具体的运行时间函数,只考虑运行时间函数的数量级,然后比较这些函数的数量级。这种方法称为
渐进表示法 。最常用的渐进表示法是大O表示法。
定义:如果存在两个正常数c与N。,使得当N>=N。时有T(N)=cF(N),则记为T(N)=O(F(N) )。
例1:设T(n)=(n+1)^2。那么,取n。=1及c=4时,T(n)<=cn^2成立。所以,T(n)=O(n^2)。
例2:设T(n)=3n^3 + 2n^2。选n。=0及c=5; T(n)<=cn^3。所以T(n)=O(n^2)。
大O表示法给出了算法在问题规模n达到一定程度后运行时间增长率的上界,因此被称为
渐进时间复杂度 ,简称为
时间复杂度。大O表示法的O是单词Order的首字母,表示“数量级”。因此,大O表示法并不需要给出运行时间的精确值,而只需要给出一个数量级,表示当问题规模很大时算法运行时间的增长是受限于哪一个数量级的函数,所以在选择F(N)时,通常选择的是比较简单的函数形式,并忽略低次项和系数。
常用时间复杂度函数
1 常量
logN 对数
N 线性
NlogN NlogN
N^2 平方
N^3 立方
2^N 指数
N! 指数
N^N 指数
常量的时间复杂度表示算法的运行时间与问题的规模无关,总是执行有限个标准操作。
时间复杂度为多项式的算法称为
多项式时间算法,时间复杂度为指数函数的算法称为指数时间算法。常见多项式时间算法的时间复杂度之间的关系为
O(1)<O(logN)<O(N)<O(NlogN)<O(N^2)<O(N^3)
指数时间算法的时间复杂度关系为
O(2^N)<O(N!)<O(N^N)
时间复杂度的计算主要依据一下两个定理:
1. 求和定理:假定T1(n)、T2(n)是程序段P1,P2的运行时间,并且T1(n)是O(f(n))的,而T2(n)是O(g(n))的。那么,先运行P1、再运行P2的总的运行时间是:
T1(n)+T2(n) = O(MAX(f(n), g(n)))。
2. 求积定理:如果T1(n)和T2(n)分别是O(f(n))和O(g(n))的,那么T1(n) * T2(n)是O(f(n), g(n))。
由以上2个定理可以得到一下的规则:
1. 每个简单语句,如赋值、输入输出语句,他们的运行时间与问题的规模无关,在每个计算机系统中运行时间都是一个常量,因此时间复杂度为O(1)。
2. 条件语句,if<条件>then<语句>else<语句>的运行时间为执行条件判断的代价,一般为O(1),再加上执行then后面的语句的代价(若条件为真),或执行else后面的语句代价(若条件为假)之和,即MAX(O(then子句), O(else子句))。
3. 与问题规模有关的循环语句是分析的重点。循环语句的执行时间是循环控制行和循环控制体执行时间的总和。循环控制行一般是一个简单的条件判断,因此循环语句的执行时间是循环体的运行时间乘循环次数。
4. 嵌套循环语句,对外层循环的每个循环周期,内层循环都要执行它的所有循环周期,因此,可用求积定理计算整个循环的时间复杂度,即最内层循环体的运行时间乘所有循环的循环次数。 例如语句:
for(i=0; i<n; i++){
for(j=1; j<n; j++) k++; }
它的时间复杂度为O(n^2)。
连接语句:利用求和定理把这些语句的时间复杂度相加。例如:
for(i=0; i<n; i++) a[i]=o;
for(i=0; i<n; i++){
for(j=1; j<n; j++) a[i]=i+j; }
由2个连续的循环组成。第一个循环时间复杂度为O(n), 第二个循环的时间复杂度为O(n^2)。根据求和定理,整段程序的时间复杂度为O(n^2)。