算法时间复杂度分析示例
为了便于朋友们理解,我将不会采用教科书上惯用的快速排序、合并排序等经典示例进行分析,而是使用一个十分简单的算法作为示例。我们先来定义问题。
问题定义:
输入——此问题输入为一个有序序列,其元素个数为n,n为大于零的整数。序列中的元素为从1到n这n个整数,但其顺序为完全随机。
输出——元素n所在的位置。(第一个元素位置为1)
LocationN(A)
{
for(int i=1;i<=n;i++)-----------------------t1
{
if(A[i] == n) ----------------------------t2
{ return i; }------------------------t3
}
}
我们来看看这个算法。其中t1、t2和t3分别表示此行代码执行一次需要的时间。
首先,输入规模n是影响算法执行时间的因素之一。在n固定的情况下,不同的输入序列也会影响其执行时间。最好情况下,n就排在序列的第一个位置,那么此时的运行时间为“t1+t2+t3”。最坏情况下,n排在序列最后一位,则运行时间为“n*t1+n*t2+t3=(t1+t2)*n+t3”。可以看到,最好情况下运行时间是一个常数,而最坏情况下运行时间是输入规模的线性函数。那么,平均情况如何呢?
问题定义说输入序列完全随机,即n出现在1...n这n个位置上是等可能的,即概率均为1/n。而平均情况下的执行次数即为执行次数的数学期望,其解为:
E
= p(n=1)*1+p(n=2)*2+...+p(n=n)*n
= (1/n)*(1+2+...+n)
= (1/n)*((n/2)*(1+n))
= (n+1)/2
即在平均情况下for循环要执行(n+1)/2次,则平均运行时间为“(t1+t2)*(n+1)/2+t3”。
由此我们得出分析结论:
为了便于朋友们理解,我将不会采用教科书上惯用的快速排序、合并排序等经典示例进行分析,而是使用一个十分简单的算法作为示例。我们先来定义问题。
问题定义:
输入——此问题输入为一个有序序列,其元素个数为n,n为大于零的整数。序列中的元素为从1到n这n个整数,但其顺序为完全随机。
输出——元素n所在的位置。(第一个元素位置为1)
LocationN(A)
{
for(int i=1;i<=n;i++)-----------------------t1
{
if(A[i] == n) ----------------------------t2
{ return i; }------------------------t3
}
}
我们来看看这个算法。其中t1、t2和t3分别表示此行代码执行一次需要的时间。
首先,输入规模n是影响算法执行时间的因素之一。在n固定的情况下,不同的输入序列也会影响其执行时间。最好情况下,n就排在序列的第一个位置,那么此时的运行时间为“t1+t2+t3”。最坏情况下,n排在序列最后一位,则运行时间为“n*t1+n*t2+t3=(t1+t2)*n+t3”。可以看到,最好情况下运行时间是一个常数,而最坏情况下运行时间是输入规模的线性函数。那么,平均情况如何呢?
问题定义说输入序列完全随机,即n出现在1...n这n个位置上是等可能的,即概率均为1/n。而平均情况下的执行次数即为执行次数的数学期望,其解为:
E
= p(n=1)*1+p(n=2)*2+...+p(n=n)*n
= (1/n)*(1+2+...+n)
= (1/n)*((n/2)*(1+n))
= (n+1)/2
即在平均情况下for循环要执行(n+1)/2次,则平均运行时间为“(t1+t2)*(n+1)/2+t3”。
由此我们得出分析结论:
t1+t2+t3 <= F(n) <= (t1+t2)*n+t3,在平均情况下F(n) = (t1+t2)*(n+1)/2+t3
定义一:Θ(g(n))={f(n) | 如果存在正常数c1、c2和正整数n0,使得当n>=n0时,0<c1g(n)<=f(n)<=c2g(n)恒成立}
定义二:Ο(g(n))={f(n) | 如果存在正常数c和正整数n0,使得当n>=n0时,0<=f(n)<=cg(n)恒成立}
定义三:Ω(g(n))={f(n) | 如果存在正常数c和正整数n0,使得当n>=n0时,0<=cg(n)<=f(n)恒成立}
设F(n)为算法A在最坏情况下F(n),则如果F(n)属于Θ(g(n)),则说算法A的渐近时间复杂度为g(n),且g(n)为F(n)的渐近确界。
还是以上面的例子为例,则在上面定义中F(n) = (t1+t2)*n+t3。则F(n)的渐近确界为n,其证明如下:
证明:
设c1=t1+t2,c2=t1+t2+t3,n0=2
又因为 t1,t2,t3均大于0
则,当n>n0时,0<c1n<=F(n)<=c2n 即 0<(t1+t2)*n<=(t1+t2)*n+t3<=(t1+t2+t3)*n恒成立。
所以 F(n)属于Θ(n)
所以 n是F(n)的渐近确界
证毕
渐近记号总结
一、定义介绍
对于某个比较简单的算法,我们有时候确实能够精确地分析出算法的复杂度,比如算法复杂度为5n^2+10n+6,但是事实上并不需要这样,因为当n足够大时,可以忽略掉低阶项和最高次项的系数,因此就引出了“渐近复杂度”,并且用“渐近记号”来表示“渐近复杂度”。
渐近记号包括:
(1)Θ(theta):紧确界。 相当于"="
(2)O (大欧):上界。 相当于"<="
(3)o(小欧):非紧的上界。 相当于"<"
(4)Ω(大omega):下界。 相当于">="
(5)ω(小omega):非紧的下界。 相当于">"
给出这些记号的定义:
对于定义的注意点:
(1)这些定义的前提是f(n)和g(n)是渐近非负的,渐近非负的意思是“当n趋于无穷大时,f(n)和g(n)都非负”。
(2)对于第4和第5条定义,需要注意是对于任意的c。
用集合论来表示这5个符号的关系:
从上面的图可以看出:
(1)如果f(n)=Θ(g(n)),则f(n)=O(g(n))且f(n)=Ω(g(n))。
(2)如果f(n)= o (g(n)),则f(n)=O(g(n))。
(3)如果f(n)=ω(g(n)),则f(n)=Ω(g(n))。
(4)如果f(n)=O(g(n)),则要么是f(n)= o (g(n)),要么是f(n)=Θ(g(n))。
(5)如果 f(n)=Ω(g(n)) ,则要么是f(n)=ω(g(n)),要么是f(n)=Θ(g(n))。
参考:http://blog.csdn.net/xiazdong/article/details/8491622
参考:http://www.cnblogs.com/leoo2sk/archive/2008/11/14/1332381.html