浅谈时间复杂度

时间:2021-07-18 00:48:46

1.时间复杂度是什么?

有人说,这还不简单,不就是在给定输入规模时,求所执行的基本操作数量吗?如下:

int n=10;
int count=0;
for(int i=0;i<n;i++){//循环次数
for(int j=0;j<n;j++){//执行深度
count
++;
}
}
//count=100

看到这个,时间复杂度无疑是O(n^2),再看看下面的

int n=10;
int count=0;
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
count
++;
}
}
//count=45

看到这个,时间复杂度也是O(n^2),这里要出来一个概念,次数和时间复杂度的区别:

第一个程序运行的次数是100(n*n=n^2),第二个程序运行的次数是45(0+1+2+3+4+...........+n-1=n*(n-1)/2),时间复杂度一样的原因是:当n趋于无穷大时可忽略常数,-1,/2可忽略。但是时间复杂度是在次数的基础上计算出来的。而次数就是循环次数*执行深度。

2.什么是大O?

比如我说一个变量x,并且有x在[a,b]这个区间,就表示了上界是a下界是b,对于变量x的取值范围来说,最大不超过b,最小不小于a。在算法中,上界就是对于一种资源的限制最大不大于的值,下界就是对于这种资源的限制最小不小于的值。这里的资源可以是时间、空间、带宽……

所以当n趋于无穷时,O(2n^2)=O(n^2),O(n*(n-1)/2)=O(n^2),O(5n)=O(n),O(5)=O(1)。

总结来说,大O表示算法执行的最低上界。

3.为什么要进行计算时间复杂度?

我们先来看张图:

浅谈时间复杂度

如果老板给你一个任务,让你对公司的账单从大到小进行排序,你可能会直接使用数据库自带的语句order by,的确,这是个好办法。如果你细致了解数据库,数据库的底层使用了B+树为数据建立了索引,时间复杂度明显降低。换个简单例子,如果老板让你把一堆数字进行排序,你可能最先想到选择排序,每次选择最小的数。老板说,这个太耗时了,你又会想到快速排序,选择一个基准数进行比较。老板又说,我给你的这些数基本有序,你又会想到插入排序,因为插入排序在基本有序的时候,算法复杂度接近O(n)。老板说,我还想快点,你想到了快速排序与插入排序的结合,等到快速排序排到很有序的时候,插入排序就有作用了。老板又说,我想在这些排序好的数字找到中间的数,这时候你可能想到,我直接数组[(0+n)/2]输出就行了,对的,因为数组本身就是一种很快的数据结构,相当于给每个数建立了索引,就可以直接取出数来,时间复杂度复杂度O(1)。

梳理一下:时间复杂度分别向O(n^2),O(nlogn),O(n),O(nlogn)+O(n),O(1)演变

复杂度 标记符号 描述
常量(Constant)

 O(1) 

操作的数量为常数,与输入的数据的规模无关。

n = 1,000,000 -> 1-2 operations 

对数(Logarithmic)

 O(log2 n) 

操作的数量与输入数据的规模 n 的比例是 log2 (n)。

n = 1,000,000 -> 30 operations

线性(Linear)  O(n)

操作的数量与输入数据的规模 n 成正比。

n = 10,000 -> 10000 operations

平方(Quadratic)  O(n2)

操作的数量与输入数据的规模 n 的比例为二次平方。

n = 500 -> 250,000 operations

立方(Cubic)  O(n3)

操作的数量与输入数据的规模 n 的比例为三次方。

n = 200 -> 8,000,000 operations

指数(Exponential)

 O(2n)

 O(kn)

 O(n!)

指数级的操作,快速的增长。

n = 20 -> 1048576 operations

 

为什么要这样演变呢?

时间复杂度的演变,就是为了更快更好的解决问题,使其效率越来越高。

另外贴出问题规模与执行时间之间的关系图:

复杂度 10 20 50 100 1000 10000 100000
O(1)

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(log2(n))

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(n)

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(n*log2(n))

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(n2)

<1s

<1s

<1s

<1s

<1s

2s

3-4 min

O(n3)

<1s

<1s

<1s

<1s

20s

 5 hours 

 231 days 

O(2n)

<1s

<1s

 260 days 

 hangs 

 hangs 

hangs

hangs

O(n!)

<1s

 hangs 

hangs

 hangs 

hangs

hangs

hangs

O(nn)

 3-4 min 

hangs

hangs

 hangs 

hangs

hangs

hangs

 

上面关于排序的优化的文章我在前面已经做出Java代码的演示,地址:从优化的角度谈谈排序

谢谢大家的阅读,博客不易,转载请注明地址。