一、从次数来看
/**
* 这段代码一共执行了n²次
* n@param n
*/
public static void fun1(int n){
//这段代码可以执行n²次
int count=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
count++;
}
}
//这段代码执行2*n次
count=0;
for(int k=0;k<2*n;k++){
count++;
}
//这段代码执行10次
count=0;
for(int k=1;k<=10;k++){
count++;
}
}
时间复杂度有以下计算规则:
①用常数1取代运行时间当中的所有加法常数
②在修改后的运行次数函数当中,只保留最高阶数
③如果最高阶项存在且不是1,则去除与这个项目相乘的常数,得到的结果就是大O阶
三个复杂度:最好时间复杂度,最坏时间复杂度,平均时间复杂度
一般情况下面,讨论的时间复杂度是最坏的
结合以下规则,参考上面的代码:
第一部分,执行了n²次,第二部分,执行了2*n次,第三部分,执行了10次,那么总共执行了
F(n)=n²+2*n+10次,只保留最高阶数,n²,同时,系数为1,那么,时间复杂度就是n²。
例题2:
public static void fun2(int n,int m){
int count=0;
for(int k=0;k<n;k++){
count++;
}
for (int k=0;k<m;k++){
count++;
}
}
这段代码的时间复杂度就是O(m+n)
例题3:
由于出现了常数,循环的次数是一个常数,已经被确定了,尽管次数已经确定了,循环了100次,所以最后只能按照第一条规则:O(1)
public static void fun6(){
int count=0;
for(int i=0;i<100;i++){
count++;
}
}
当没有循环语句的时候,仍然按照之前的规则。 for(int k=0;k<2*n;k++){ }
例题4:经典排序算法:冒泡排序
public static void bubbleSort(int [] arr){
int temp;
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
第一次进入内层for循环的时候,需要进行n-1次,第二次进入时候,需要进行n-2次......最后一次进来时候,1次,那么一共需要进行n*(n-1)/2次。按照时间复杂度的分析,时间复杂度就是O(n²)
例题5:递归
public static int fun(int n){ return n<2?1:n*fun(n-1); }
举个例子,当n为5时候,原来的方法会变成
5*fun(4)
=5*4*fun(3)
=5*4*3*fun(2)
=5*4*3*2*fun(1)
=5*4*3*2*1
一共递归了4次,因此,此递归算法的时间复杂度为O(n)
例题六:二分查找
public static int binarySearch(int[] arr, int value) { int begin = 0; int end = arr.length - 1; //二分查找的时间复杂度分析 //第一次查找,可能需要进行n次 //第二次查找,可能需要n/2次 //... //直到最后一次变成1次 //即:N/(2的x次方)=1,其中x为次数 //则:x=log以2为底n的对数 while (begin <= end) { int mid = begin + (end - begin) / 2; if (arr[mid] < value) { begin = mid + 1; } else if (arr[mid] > value) { end = mid - 1; } else { return mid; } } return -1; }
因此,二分查找的时间复杂度就是O(logN)(对数阶一般省略底数)
空间复杂度:本身是衡量算法浪费内存的情况
例一、回到刚刚的冒泡排序,此时借助了一个辅助变量temp,尽管在循环当中只是重复为当前的数字赋值,但是一直没有产生新的变量,因此空间复杂度也是o(1)
本文含有隐藏内容,请 开通VIP 后查看