目录
1. 算法的效率
2 时间复杂度
2.1 时间复杂度的概念
2.2 大O渐进表示法
2.3 常见算法的时间复杂度分析
3. 空间复杂度
3.1 常见空间复杂度分析
我们在写一个算法的时候如何判断这个算法的好坏呢?我们主要从效率来分析,而效率包括时间效率和空间效率
在计算机科学中,时间复杂度是一个数学函数,它定量的描述了算法的运行时间,我们把算法中基本的语句执行的次数称为算法的时间复杂度
所谓基本语句在这里指重复执行的语句
代码基本语句执行次数分析
我们看这样一段代码:
public class Test {
public void func1(int N){
int count = 0;
for(int i = 0;i < N;i++){
for(int j = 0;j < N;j++){
count++;
}
}
for(int k = 0;k < 2*N;k++){
count++;
}
int M = 10;
while((M--) > 10){
count++;
}
}
}
分析一下fun1的基本操作执行了多少次,在fun1中,基本操作也就是count++执行了多少次
经分析得:fun1执行的基本操作次数为:F(N) = N^2 + 2N + 10
当N=10时,F(N)=130
当N=100时,F(N) = 10210
当N=1000时,F(N) = 1002010
我们从中发现:当N越大时,2N+10对真实的执行次数影响很小,所以实际中我们计算时间复杂度不一定要精确的执行次数,只需要大概的执行次数,所以这里使用大O渐进法表示时间复杂度
大O渐进法
对上述fun1的时间复杂度用大O渐进法表示:
故fun1的时间复杂度为:O(N^2)
算法时间复杂度的三种情况
比如在一个数组中查找某个值为n的数:
我们实际关注的是算法的最坏情况,以算法的最坏情况作为该算法的时间复杂度,故数组中查找某个数据的时间复杂度为O(N),N为数组的长度
实例1
public void fun2(int N){
int count = 0;
for(int k = 0;k < 2*N;k++){
count++;
}
int M = 10;
while(M > 0){
count++;
M--;
}
}
实例2
public void fun3(int N,int M){
int count = 0;
for(int i = 0;i < M;i++){
count++;
}
for(int j = 0;j < N;j++){
count++;
}
}
实例3
public void fun4(){
int count = 0;
for(int i = 0;i < 100;i++){
count++;
}
}
冒泡排序的时间复杂度分析
public void bubbleSort(int[] array){
for(int i = 0;i < array.length-1;i++){
for(int j = 0;j < array.length-1-i;j++){
if(array[j] > array[j+1]){
int t = array[j];
array[j] = array[j+1];
array[j+1] = t;
}
}
}
}
二分查找的时间复杂度分析
public int binarySearch(int[] array,int value){
int begin = 0;
int end = array.length-1;
while(begin < end){
int mid = begin+((end-begin)>>1);
if(array[mid] < value){
begin = mid+1;
}else if(array[mid] > value){
end = mid-1;
}else {
return mid;
}
}
return -1;
}
我们经分析出二分查找的时间复杂度为O(lgN),所以在刷题的时候有些题目对算法要求O(lg2),在没有思路的时候就可以考虑用二分法可不可以解决
阶乘递归的时间复杂度分析
public long factorial(int N){
return N < 2 ? N : factorial(N-1)*N;
}
斐波那契递归的时间复杂度分析
public long factorial(int N){
return N < 2 ? N : factorial(N-1) + factorial(N-2);
}
空间复杂度是对一个算法在运行的过程中对临时占用内存空间大小的一个量度,空间复杂度的核心就是看算法中是否申请了额外空间,计算规则根时间复杂度的计算规则类似,也使用大O渐进表示法
对于递归算法的空间复杂度:单次递归需要的空间 * 递归的深度
实例1
public void bubbleSort(int[] array){
for(int i = 0;i < array.length-1;i++){
for(int j = 0;j < array.length-1-i;j++){
if(array[j] > array[j+1]){
int t = array[j];
array[j] = array[j+1];
array[j+1] = t;
}
}
}
}
发现该冒泡排序没有申请额外的空间,故空间复杂度为O(1)
实例2
long[] fibonacci(int n) {
long[] fibArray = new long[n + 1];
fibArray[0] = 0;
fibArray[1] = 1;
for (int i = 2; i <= n ; i++) {
fibArray[i] = fibArray[i - 1] + fibArray [i - 2];
}
return fibArray;
}
实例3
public int fun(){
int[] arr = new int[10];
arr[0] = 1;
return arr[0];
}
说明:只要申请空间的时候指定了大小,不论多大,空间复杂度为O(1)
实例4
public long factorial(int N){
return N < 2 ? N : factorial(N-1)*N;
}