文章目录

  • 复杂度
  • 时间复杂度
  • 规则
  • 常见的时间复杂度
  • 最好、最坏、平均时间复杂度
  • 空间复杂度
  • 规则
  • 常见的空间复杂度


复杂度

复杂度也叫渐进复杂度,包括时间复杂度空间复杂度,用来分析算法执行效率与数据规模之间的增长关系

复杂度分析可以在初期帮助程序员预估该程序的性能耗费

时间复杂度用于表示算法的时间耗费与数据规模增长之间的关系

空间复杂度用于表示算法的存储空间与数据规模增长之间的关系

时间复杂度

规则

  1. 总复杂度等于量级最大的那段代码的复杂度,比如说一个程序中存在两段不同时间复杂度的代码块:
int f(int n) {
  	int sum = 0;
    
    for (int i = 0; i < n; ++i) {
    	sum ++;
    }
  
  	for (int i = 0; i < n; ++i) {
    	for (int j = 0; j < n; ++j) {
            sum ++;
        }
 	} 
    
    return sum;
 }

第一个for循环的时间复杂度T1,和第二个嵌套for循环的时间复杂度T2分别为:
Java 代码复杂度怎么算_复杂度
那么整个程序的时间复杂度为:
Java 代码复杂度怎么算_复杂度_02

  1. 如果量级大的代码块有多个,而我们无法事先评估谁的量级大,就不能简单地省略其中一个,例如:
int f(int n, int m) {
  	int sum = 0;
  
  	for (int i = 0; i < n; ++i) {
   		sum ++;
 	} 
 	
 	for (int i = 0; i < m; ++i) {
 		sum ++;
 	}
     
	return sum;
 }

该函数的时间复杂度为:
Java 代码复杂度怎么算_复杂度_03

  1. 乘法法则: 嵌套代码的复杂度等于嵌套内外代码复杂度的乘积,例如:
int f(int n, int m) {
  	int sum = 0;
  
  	for (int i = 0; i < n; ++i) {
    	for (int j = 0; j < m; ++j) {
            sum += j;
        }
 	} 
     
	return sum;
 }

该函数的时间复杂度为:
Java 代码复杂度怎么算_时间复杂度_04

常见的时间复杂度

Java 代码复杂度怎么算_空间复杂度_05

Java 代码复杂度怎么算_时间复杂度_06

Java 代码复杂度怎么算_复杂度_07

Java 代码复杂度怎么算_Java 代码复杂度怎么算_08

对于常量复杂度而言,执行时间不随 n 的增大而增长的代码,我们都记作 O(1) 。 一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)

对于对数阶复杂度而言, 不管是以 2 为底、以 3 为底,还是以 10 为底,我们可以把所有对数阶的时间复杂度都记为O(logn)

对于指数阶、阶乘阶复杂度而言, 当数据规模 n 增大,算法的执行时间会急剧增加 ,因此这两类时间复杂度的算法是非常低效的算法不推荐使用

最好、最坏、平均时间复杂度

上述情况是程序必须执行完所有代码得出的时间复杂度。而在很多情况下,我们不需要进行完整的遍历或递归,例如查找一个数组中是否存在5:

int val[n];

bool find() {
	for (int i = 0; i < n; i++) {
		if (val[i] == 5) {
			return true;
		}
	}
	
	return false;
}

最好情况时间复杂度是最理想情况下执行这段代码的时间复杂度,体现在上述代码中,就是数组第一个元素是5,因此最好情况时间复杂度为O(1)

最坏情况时间复杂度是最糟糕情况下执行这段代码的时间复杂度 ,体现在上述代码中,就是数组中不存在元素5,因此最坏情况时间复杂度为O(n)

平均情况时间复杂度是考虑所有可能发生的情况、概率、以及对应耗费的时间,然后取平均值,体现在上述代码中,就是考虑n+1种情况(5出现在0~n-1位置 和 5没有出现)及其概率、对应耗费的时间,得到:
Java 代码复杂度怎么算_空间复杂度_09
由于时间复杂度可以省略掉系数、低阶、常量,把这个公式简化之后得到的平均时间复杂度就是 O(n)

空间复杂度

规则

规则与时间复杂度的三点类似,不再赘述

我们可以通过空间复杂度,来预估程序所耗费的内存。比如:

const int N = 1000000;

int[] val = new int[N];

int型占四字节,对于O(n)空间复杂度的程序来说,当n为1e6时,耗费的内存为:
Java 代码复杂度怎么算_Java 代码复杂度怎么算_10

常见的空间复杂度

比较常见的空间复杂度有:
Java 代码复杂度怎么算_空间复杂度_11
相比时间复杂度, O(logn)、O(nlogn)等对数阶复杂度平时几乎用不到~