什么是时间复杂度?(个人理解,有基础的可以直接跳到后面的计算部分)
刚学习时间复杂度的小伙伴可能对这个是似懂非懂,用大白话来说就是,你这个程序跑起来,我不管你在天河一号还是在你的笔记本上,到底需要花费的时间是一个什么样的数量级。比如O(n²)表示就是运行的时间是n²级别的,当n无穷大时,运行时间就是按n²的规模进行增长的。
同时要注意,即便我们的程序有一万行代码,如果不存在循环,每一行代码是独立运行的,他的时间复杂度也只有O(1),就算你输入了无限多个数据,你也只需要处理这一万行代码就够了,所以运行时间是常数级别的,远不如三行代码的for循环大。
可能又有的小伙伴要问了,那我在我笔记本是跑一万行代码,肯定没我的for循环执行时间快啊?我刚开始学的时候,也是有这个疑问的,其实这是因为,我们个人学习的时候跑的代码,数据量很小,几百几千的都已经算很大了,但是在科技这么厉害的今天,我们手上的个人电脑已经能够在很短的时间里处理完这些数据,以至于我们感觉不到差异,但是当我们就业以后,可能我们的代码需要应用到数以万计的数据量中,此时你就会发现,不同的时间复杂度带来的运行时间差别有多大了。因此给出结论:时间复杂度≠时间
显然,不同程序的时间复杂度也不是相同的,取决于代码逻辑,那么在实际做题中,该怎么计算我们的代码时间复杂度呢?
首先,题目所给代码无非两种情况,一种是只有一层循环,如while循环。另一种就是多层循环,如for多层嵌套。对于这两种情况分别有不同步骤,归根结底就一句话:找到每次循环的运行次数并累加。
(看着很多其实是,学会演草纸上迅速秒杀)
单层循环(四步解决)
1.找到跳出循环的条件
2.设循环次数为a
3.当a=1、2、3...时,只看使循环变量i变化的语句分别算出i的值,找到规律后写出a与变量i的关系式
4.带入循环条件解出a的值,O(a)即为时间复杂度
例1:
求下列代码的运行时间复杂度
i=1;k=0;
while(i<n-1){
k=k+10*i;
i++;
}
解答:
1.跳出循环的条件为i≥n-1
2.设循环次数a
3.a=1时,循环一次,i++执行一次,i的值为2 a=2时,循环两次,i++执行两次 ,i的值为3 以此类推,a=a时即循环次数为a时,i++执行a次,i的值为a+1
4.将i=a+1代入i≥n-1解出a≥n-2 故循环次数为n-2次,时间复杂度为O(n-2)=O(n)
例2:
求下列代码的运行时间复杂度
x=2;
while(x<n/2)
x=2*x;
解答:
1.跳出循环的条件为x≥n/2
2.设循环次数a
3.a=1时,循环一次,x=2*x 执行一次,x的值为4 a=2时,循环两次,执行x=2*x执行两次 ,x的值为8 以此类推,a=a时即循环次数为a时,x=2*x 执行a次,x的值为2ᵃ⁺¹
4.将x=2ᵃ⁺¹代入x≥n/2解出 a≥log₂n/2-1 故循环次数为log₂n/2-1 (可能非整数,需要向下取整),时间复杂度为O(n-2log₂n/2-1 )=O(logn)
多层循环(两步解决)
1.找到最内层主要语句一次循环需要执行的次数a
2.对a逐层累加(留意循环变量每次不是变化1 的情况,要用到一些规律或者数列性质求和)
3.计算得出结果
例1:
求下列代码的运行时间复杂度
int m=0,i,j;
for(i=1;i≤n;i++){
for(j=1;j≤2*i;j++){
m++;
}
}
解答:
1.最内层的语句每次循环执行次数为a=1 (只有一句代码,每次只执行一次)
2.对a=1从j=1到j=2*i进行累加,并对这个整体在i=1到i=n进行累加,参考计算过程如下图所示:
故循环体代码执行次数为n(n+1)/4
时间复杂度为O(n(n+1)/4)=O(n²)
例2:
求下列代码时间复杂度
int sum=0;
for(int i=1;i<n;i*=2){
for(int j=0;j<i;j++){
sum++;
}
}
解答:
1.最内层循环语句执行次数=a1
2.对a=1从j=0到j=i-1进行累加,并对这个整体在i=1到i=n-1进行累加(并注意这里的i每次不是增加1,而是×2),参考计算过程如下图所示:
因此运行的次数为2n+1
时间复杂度为O(2n+1)=O(n)
有什么不懂的可以在评论区留言,我会及时解答