前言:
最近,在学习数据结构与算法中的算法时间复杂度。其实,在学它之前,自己也会这样想,现在电脑中CPU运行速度这么快且相关的性能也显著提高,为什么还要去学习怎么去提高算法效率,怎么去计算或者表示算法时间复杂度呢?当然,上述的话还不无道理,然而,当你能够去优化你的代码,去试着去想怎么去写出更为高效的代码时,你的能力就在此能够提高一大层。还有就是,就算现在电脑的运行速度这么快,但是你只追求写出算法,而不去追求更为高效的算法的话,电脑运行速度的提升速度还是赶不上复杂算法的更新。好了,不多说了,现在进入正题:
1.算法时间复杂度的定义:
在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的一个函数。
1.1.常数阶:
int a=1,b=1,sum; //执行一次
sum=a+b; //执行一次
printf("%d",sum); //执行一次
上面的算法f(n)=3,可知该算法的时间复杂度是一个常数阶,对于像此类的算法时间复杂度,我们都以O(1)表示,而不是O(3)表示,统一表示为O(1).
1.2.线性阶:
大家应该都知道线性函数吧,这里的线性阶和上述是同样的道理。
int i;
for(i=0;i<n;i++) //执行n次
可知上述的算法时间复杂度就是用O(n)表示,这就代表线性阶。
1.3.对数阶:
int a=1;
while(a<n)
{
a=a*2;
}
随着循环的进行,a的值不断靠近n的值,也就是说有多少个2相乘最后大于n的值,则会退出循环。设为x个2相乘。有等式x= l o g 2 n log_{2}n log2n,所以这个循环的算法时间复杂度为O(logn);
1.4.平方阶:
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
}
}
内循环为n此,外循环为n此,最后执行
n
2
n^{2}
n2次,所以这个循环的算法时间复杂度为O(
n
2
n^{2}
n2),称其为平方阶。
不过这里要注意的是,还有一种循环:
int i,j;
for(i=0;i<n;i++)
{
for(j=i;j<n;j++)
{
}
}
当i=0时,内循环执行n此,当i=1时,内循环执行n-1次,以此类推,最后为n+(n-1)+(n-2)+…+1;
由等差知识可知其最后的值为:
n
2
2
\frac{n^2}{2}
2n2+
n
2
\frac{n}{2}
2n,当这样的表达式时,我们会将其的算法时间复杂度用O(
n
2
n^{2}
n2)表示,因为,在n趋于无穷大时,其常数和最高次数的的系数即一些低的系数直接忽略。立方阶等都是这样考虑。
当你在写代码时定义相关函数,那怎么去算它的时间复杂度呢?当然,这个问题很简单,我们依旧按照相同的方法去计算即可,最后将其相加,得出最终结果。
2.常见的时间复杂度:
3.最坏情况和平均情况:
我们在写一段代码时,每每要去考虑该算法在最坏情况下其效率会是什么样的,其执行时间所占内存能否达到标准,达到合格。最坏情况的运行时间是一种保证,保证你的算法能够运行,在应用中这是十分重要的。
对于平均情况而言,这是所有情况最有意义的,因为它是期望的运行时间。
参考文献:
《大话数据结构》
大家如果想要该书的PDF版可以关注我,我免费发你。😄
希望大家多多支持,多多指教。
😃😃😃
浩瀚星空,你我刚好相遇。