![image-20201231130906583](https://gitee.com/panqiyi/pqimg/raw/master/20201231130906.png)
时间复杂度:估算程序指令执行的次数
时间复杂度计算案例
注意:为了方便,省略了方法的修饰,只保留了方法名
method1(){
System.out.println("祝你看了这篇文章"); //执行1次
System.out.println("诸事顺利"); //执行1次
System.out.println("万事如意"); //执行1次
}
// 1+1+1 = 3
method2(){
for(int i=0;i<5;i++){ //i=0 执行1次;i<5 判断5+1次,等于5时判断后退出;i++ 执行5次
System.out.println("点赞发财!"); //执行5次
}
} //1+(5+1)+5+5 = 17
method3(int n){
for(int i=0;i<n;i++){ //i=0 执行1次;i<n 执行n+1次;i++ 执行n次
System.out.println("点赞好运!"); //执行n次,你会有n次好运哦
}
} //1+(n+1)+n+n = 3n+2
method4(int n){
for(int i=0;i<n;i++){ //i=0 执行1次;i<n 执行n+1次;i++ 执行n次
//整个内层循环 执行n次
for(int j=0;j<n;j++){ //j=0 执行1次;j<n 执行n+1次;j++ 执行n次
System.out.println("你很帅"); //执行n次
}
}} //外层2n+2; 复杂度:2n+2+n*(3n+2) = 3n^2+4n+2
method5(int n){
for(int i=0;i<n;i++){ //i=0 执行1次;i<n 执行n+1次;i++ 执行n次
// 整个内层循环执行n次
for(int j=0;j<15;j++){ //j=0 执行1次;j<15 执行15+1次;j++ 执行15次
System.out.println("高山流水"); //执行15次
}
} } // 复杂度:2n+2+n*(47) = 49n+2
method6(int n){
while((n=n/2)>0){
System.out.println("葵花宝典");
}
}
/*
假如:n=8 ; 8/2=4 执行1次;4/2=2 执行1次;2/2=1 执行1次;1/2=0.5=0 执行判断后,不进入循环体。
所以循环体执行3次,判断执行3+1次;2^3=8---->log2(8)=3
n=16 ; 16/2=8 执行1次;8/2=4 执行1次;4/2=2 执行1次;2/2=1 执行1次;
所以循环体执行4次,判断执行4+1次;2^4=16---->log2(16)=4
所以时间复杂度:log2(n)+(log2(n)+1) = 2log2(n)+1
log2(n):循环体内执行次数,(log2(n)+1):判断语句执行次数
*/
method7(int n){
while((n=n/5)>0){
System.out.println("欲练神功");
}
} // 由method6可知,复杂度:log5(n)+(log5(n)+1) = 2log5(n)+1
// log5(n):循环体内执行次数, (log5(n)+1):判断语句执行次数
method8(int n){
for(int i=1;i<n;i=i*2){
for(int j=0;j<n;j++){ //j=0 1次,j<n n+1次,j++ n次
System.out.println("你懂的");// n次
}
}}
/*
i=1, i=1*2=2, i=1*2*2=4, i=1*2*2*2=8 ; 所以i<n执行次数=log2(n)+1; (多1是判断一次不满足条件退出循环时)
如果n=8, i<n 执行判断4次 log2(8)+1; 内层整个循环执行log2(8)=3次
复杂度:1+(log2(n)+1)+log2(n)+[log2(n)*(1+(n+1)+n)] = 2nlog2(n)+4log2(n)+2
左到右:1:i=1执行次数; log2(n)+1:i<n执行次数; log2(n):i=i*2执行次数
[log2(n)*(1+(n+1)+n)]:log2(n):整个内层循环执行次数;(1+(n+1)+n):内层循环的执行次数
*/
method9(int n){
for(int i=0;i<n;i++){ // i=0 执行1次;i<n 执行n+1次;i++ 执行n次
for(int j=i;j<n;j++){
System.out.println("谢谢点赞");
}
}}
/*
i=0,内部执行n次;i=1,内部执行n-1; i=2,内部执行n-2;…… i=n-1,内部循环执行1次。等差数列
=n*(n+1)/2 = (1/2)n^2+(1/2)n;
所以内部循环除了j<n需要多执行判断一次外,其他都是执行(1/2)n^2+(1/2)n次
时间复杂度:2n+2+4*((1/2)n^2+(1/2)n)+1
4*((1/2)n^2+(1/2)n)+1 : 内层循环执行次数
int j=i; j<n; j++; System.out.println("谢谢点赞");
这4条除了 j<n 执行了 (1/2)n^2+(1/2)n +1
其他3个都是 (1/2)n^2+(1/2)n
*/
大O表示法
上面的时间复杂度的表示还是较复杂,我们一般都使用大O表示法来简化表示时间复杂度。
1、复杂度为常数,如23,9999,等等 都表示为O(1)
2、复杂度包含n时,省略系数与常数项,只取n的最高阶项
如:2n+45 为 O(n) ; 4n^3 + 6n^2+n 为O(n^3)
3、复杂度为对数时:如log5(n)、log2(n) 等等 都表示为 O(logn)
4、省略低阶,只取高阶 (即取最大的)
如:logn+nlogn 表示为O(nlogn)
复杂度的大小
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
复杂度越小,则说明你的代码越好
那么上面的 method1~method9 用大O表示法如下:
method1: 1+1+1 = 3 即O(1)
method2: 1+(5+1)+5+5 = 17 即O(1)
method3: 3n+2 即O(n)
method4: 3n^2+4n+2 即O(n^2)
method5: 49n+2 即O(n)
method6: 2log2(n)+1 即O(logn)
method7: 2log5(n)+1 即O(logn)
method8: 2nlog2(n)+4log2(n)+2 即O(nlogn)
method9: 2n+2+4*((1/2)n^2+(1/2)n)+1 即O(n^2)