文章目录
前言
通过时间、空间复杂度分析,可以衡量我们编写代的算法代码的执行效率。其表示方法称为:大O(时间度)复杂度表示法。(本文总结均是看完王争老师《数据结构与算法》课程后,根据其文章进行总结,等后续忘记以便翻阅)
一、大O表示法是什么?
大O时间复杂度实际上并不具体代表代码的真正执行时间,而是代表代码执行时间随数据规模增长的变化趋势,所以也叫作渐进时间复杂度,简称时间复杂度。一般分析中的低阶、常量以及系数并不左右增长趋势,所以都可以忽略。
二、时间复杂度分析
以下是三个较为实用的方法
1.只关注循环执行次数最多的一段代码
代码如下(示例):
int cal(int n){
int sum = 0;
int i = 1;
for(;i <= n;++i){
sum = sum + i;
}
return sum;
}
循环执行次数最多的就是for循环中的判断与sum累加,这两行代码被执行了n次,所以总的时间复杂度就是O(n)。
2.加法法则
代码如下(示例):
暂时不添加代码
公式:T1(n) = O(f(n)), T2(n) = O(g(n)); 那么T(n) = T1(n) + T2(n) = max(O(f(n)), O(g(n))) = O(max(f(n),g(n)))。也就是:总的时间复杂度就等于量级最大的那段代码的时间复杂度。
3.乘法法则
代码如下(示例):
暂时不添加代码
公式:假设T1(n) = O(n), T2(n) = O(n * n),那么T1(n) * T2(n) = O(n * n * n)。即:嵌套代码的复杂等于内外代码复杂度的乘积,乘法法则可以看成是嵌套循环。
三、四个复杂度分析方面的知识点
1.最好情况时间复杂度(best case time complexity)
代码如下(示例):
int Find(int[] array, int n. int x){
int i = 0;
intpos = -1;
for(;i <= n;++i){
if(x == array[i]){
pos = i;
break;
};
}
return pos;
}
上述例子实现功能:在一个无序数组(array)中,查找变量x出现出现的位置。如果数组中第一个元素正好是x,那么时间复杂度就是O(1),即最好情况时间复杂度(在最理想的情况下,执行这段代码的时间复杂度);如果数组中不存在变量x,那我们就需要把整个数组都遍历一遍,时间复杂度就成了O(n),即最坏情况时间复杂度(在最糟糕的情况下,执行这段代码的时间复杂度)。
2.最坏情况时间复杂度(worst case time complexity)
见1.最好情况时间复杂度
3.平均时间复杂度(average case time complexity)
引用最好情况时间复杂度中的例子,要查找变量x在数组中的位置,有n+1种情况(在数组的0~n-1位置中和不在数组中),为了方便理解,假设x在数组中和不在数组中的概率各为1/2,而在数组中各个位置的概率也一样,那么出现在数组中各个位置的概率为1/(2n)。那么平均时间复杂度的计算就为:
该值为概率轮中的加权平均值,也叫期望值,所以平均时间复杂度的全程应该叫加权时间复杂度或期望时间复杂度。
但是大多数情况下,不需要区分最好、最坏、平均这三种情况,一般使用一个复杂度就满足需求。只有同一块代码在不同的情况下,时间复杂度有量级的差距,才会使用这三种时间复杂度表示法来分析。
4.均摊时间复杂度(amortized time complexity)
对应的分析方法叫摊还分析(或平摊分析)。对一个数据结构进行一组连续操作中,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作之间存在前后连贯的时序关系,这个时候,我们就可以将这一组操作放在一块儿分析,看是否能将较高时间复杂度那次操作的耗时,平摊到其他那些时间复杂度比较低的操作上。而且,在能够应用均摊时间复杂度分析的场合,一般均摊时间复杂度就等于最好情况时间复杂度。
四、空间复杂度分析
空间复杂度(渐进空间复杂度),表示算法的存储空间与数据规模之间的增长关系。
总结
复杂度(渐进负责度):包括时间复杂度(渐进时间复杂度)与空间复杂度(渐进空间复杂度),用来分析算法执行效率与数据规模之间的增长关系。可以粗略地表示为,越高阶复杂度的算法,执行效率越低。