也许对于学过数据结构的同胞来说,这是一个再简单不过的问题,但对于刚起步的菜鸟来说,这是个很宝贵的资源,在各大oj过题,时有超时现象出现,苦逼的我只能换思路,换代码,但自从有了时间效率分析,妈妈再也不用担心我会超时了,那么接下来,我便用最菜鸟的语言谱写较完善的时间效率分析。
算法的时间效率分析主要在于计算基本语句的运算次数,表示为T(n)=O(f(n)),f(n)为运算次数,下面通过几个例子来说明吧
1.普通程序
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
{
C[i][j] = 0; //基本语句1
for(k = 0; k < n; k++)
c[i][j] = c[i][j] + a[i][k] * b[k][i]; //基本语句2
}
如上是求两个n阶矩阵相乘运算的算法时间复杂度,(不懂代码含义不用紧,此处只用来讲时间效率问题)语句1 历经两个for语句,每个for进行n次运算,故计算语句1次数为c1*n²,c1为常数(计算方式不同,基本语句常数就不同,如语句2有加乘),
同理可得,最后T(n) = f(n) = c1*n² + c2 * n*n*n所以该算法的时间复杂度为T(n) = O(n的3次方)
2.变量增长
for(i=1;i <= n; i = 2 * i)
printf("i = %d\n",i); //基本语句
不难看出,第一次i == 1,第二次 i==2,第三次 i==4 ,依此可知,2的f(n)次方 < N,
所以f(n) <= Ibn(Ib为两边log后的化简) 故f(n) <= O(Ibn)。
3.有些数据元素取值不同,则算法复杂度也会不同,此时算法的时间复杂度应是数据元素最坏情况下取值的时间复杂度(简称最坏时间复杂度)。
void BubbleSort(int a[], int n)
{
int i,j,flag = 1;
int temp;
for(i = 1;i < n && flag == 1; i++)
{
flag = 0; //基本语句1
for(j = 0; j < n -i ; j++)
{
if(a[j] > a[j+i])
{
flag = 1; //基本语句2
temp = a[j]; //基本语句3
a[j] = a[j+1]; //基本语句4
a[j+1] = temp; //基本语句5
}
}
}
}
如上为冒泡排序的代码,当某次排序过程中木有任何数组元素需要交换时,表明flag = 0标记而结束。但是最坏的情况下,每次排序过程中都至少有一对数组元素交换位置,因此,基本语句1最多只进行n次,其余语句由于冒泡排序,一次for排好一次数,下次便少排一次数,即第一次n-1次,第二次,n-2次。。依次类推第n - 1次时,1次,故f(n) ≈ n + 4 * (n2/2)(等差数列求和,4个基本元素) 故 T(n) = O(n2)。
4.一些算法因数据处理位置不同而不同,此时应计算等概率取值情况下的平均时间复杂度。
下面算法在一个有n个数据元素的数组a中删除第i个位置的数组元素,要求删除成功时,数据元素减1,求该算法的时间复杂度。
int Delete(int a[],int n,int i)
{
int j;
if(i < 0 || j < n ) return 0;
for(j = i + 1; j < n; j++) a[j - 1] = a[i];
n--;
return 1;
}
该算法随删除数据位置不同而不同,例如删除位置在第一位,则后面n-1个数据都要向前移动,若删除位置在最后一位,各位就不用移位了,设E为移动数据的平均次数,有E = [(n-1) + (n-2) +....+ 2 + 1 + 0] / n =(n-1)/2,所以T(n) = O(n)。