时间复杂度
1.概念
时间复杂度度全称为渐进式时间复杂度:代表的是不是代码的实际执行时间而是表示代码执行时间随着数据规模增大的变化趋势。通常用大O来表示。
2.时间复杂度分析算法
2.1.加法原则
代码的总的复杂度等于量级最大的那段代码的复杂度
2.2乘法原则
嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
2.3常见的时间复杂度量级
O(1):代码的执行时间不随着数据规模n变化 注意:复杂度是O(1)不代表就执行了一条代码
O(logn)、O(nlogn):
1 i=1;
2 while(i<n){
3 i=i*2;
4 }
我们只要知道第3行代码执行了多少遍就知道整段代码的时间复杂度。
i的取值是一个等比数列 当(2^x)>n的时候循环终止,也就是 2^0 ,21,22,……,2^x。
对于2^x=n 我们能得到 x=log2n(以2为底),当这段执行n遍后 时间复杂度就是nlogn。
常见的复杂度的增长趋势有大到小排列:O(n^2) > O(nlogn) > O(n) > O(n^2) > O(n) > O(logn) > O(1)
2.4最好时间复杂度和最坏时间复杂度
这两种复杂度都是在极端极端情况下的复杂度,最好时间复杂度就是在最好情况下执行这段代码,最坏时间复杂度反之。
1 int find (int [] array,int n,int x){ //array是一个无序数组 n表示数组长度 查找x变量的位置 如果没有找到返回-1
2 int i=0;
3 int pos=-1;
4 for(;i<n;++i){
5 if(array[i]==x){
6 pos=i;
7 break;
8 }
9 }
10 return pos;
11 }
上面这段代码
如果x的位置在第一个就不需要遍历剩余的n-1个数据了,那么最好时间复杂度就是O(1)
如果x的位置不在数组里面就会遍历整个数组,那么最坏时间复杂度就是O(n)
2.5平均时间复杂度
平均时间复杂度指的是代码被重复执行无数次,对应的时间复杂度的平均值。
2.6均摊时间复杂度
这是时间复杂度比较特殊的情况,并不是很常用,但是也有对应的分析方法:摊还分析法,也称平摊分析法。
应用场景:对一个数据结构进行一组连续操作,在大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作之间存在前后连贯的时序关系,这样我们需要把这一组操作放在一起分析,观察是否能将较高时间复杂度的那次操作的耗时均摊到其他比较低时间复杂度的操作上。一般应用均摊时间复杂度分析的场景中,一般均摊时间复杂度等于最好时间复杂度。
1 int[] array=new int [n] //array和count是类成员变量或者全局变量
2 int count=0; // 表示数组中元素个数
3 void insert(int val){
4 if(count==array.length){
5 int sum=0;
6 for (int i=0;i<array.length;i++){
7 sum=sum+array[i];
8 }
9 sout(sum);
10 count=0;
11 }
12 array[count]=val;
13 ++count;
14 }
这段代码实现了向数组中插入数据,数组有未占用的空间,就直接插入数据
当数组满了后利用for循环对数组遍历求和并清空数组
对这段代码分析时间复杂度:
最好时间复杂度就是直接插入O(1),最坏时间复杂度是O(n),平均时间复杂度也是O(n),但是和上面find 方法也不一样,
首先就是极端情况下find方法的复杂度为O(1),而insert方法为O(n)
还有就是insert方法O(1)和O(n)的出现很有规律,一般是在一个 O(n)时间复杂度的插入,后面紧跟着n-1个O(1)时间复杂度的插入不断循环。
如果我们把耗时多的那次操均摊到接下来的n-1次耗时少的操作中,均摊下来可以认为连续插入操作的均摊时间复杂度是O(1)