目录
时间复杂度
若存在函数f(n),当n趋于无穷大时,T(n) / f(n)的极限值是不为零的常数,那么就称f(n)是T(n)的同数量级函数。记作T(n) = O(f(n)),也称之为O(f(n)),O为算法的时间复杂度。
知道了什么是时间复杂度后,那么新的问题就来了,我们如何去推导时间复杂度呢?首先我们要遵循下面几点规则:
- 如果运行时间是常数量级,则用常数1表示
- 只保留时间函数中的最高阶项
- 如果最高阶项存在,则省去最高阶项前面的系数
时间复杂度计算
这样全概念型的大家可以不太理解,这里我们举例子说明具体含义:
示例1:
T(n) = 7n # 最高阶项为7n,省去系数7,时间复杂度为:T(n) = O(n)
示例2:
T(n) = 7log(n) # 省去系数7,时间复杂度为:T(n) = O(logn)
示例3:
T(n) = 5 # 只有常数量级,时间复杂度为:T(n) = O(1)
示例4:
T(n) = 2.5n^2 + 2.5n # 保留最高阶项,时间复杂度为:T(n) = O(n^2)
四种时间复杂度排序:O(1) < O(logn) < O(n) < O(n^2)
空间复杂度
在运行程序时,我们往往会根据需要存储一些临时的中间数据,以便于后续指令可以更方便的执行。
在时间复杂度相同的情况下,算法占用的内存空间越小越好。程序占用空间大小的计算公式为S(n) = O(f(n)),f(n)为算法所占存储空间的函数。
空间复杂度计算
常量空间
当算法存储空间大小固定,和输入规模没有直接的关系时,空间复杂度记作O(1)。
def fun(n):
i = 3
线性空间
当算法分配的空间是一个线性的集合【如列表】时,并且集合大小和输入规模n成正比时,空间复杂度记作O(n)。
def fun(n):
array = [[0] * n]
二维空间
当算法分配的空间是一个二维列表集合,并且集合的长度和宽度都与输入规模n成正比时,空间复杂度记作O(n^2)。
def fun(n):
matrix = [[0] * n] * n
递归空间
计算机在执行递归程序时,会专门分配一块内存,用来存储"函数调用栈"。
"函数调用栈"包括进栈和出栈两种行为。
- 进栈:当进入一个新函数时,执行入栈操作,把调用的函数和参数信息压入栈中。
- 出栈:当函数返回时,执行出栈操作,把调用的函数和参数信息从栈中弹出。
def fun(n)
if n > 0
fun(n - 1)
假设传入的值为5,入栈将参数(n = 5)先入栈,接下来再调用相同的方法将所有元素全部入栈
method | fun |
n | 1 |
n | 2 |
n | 3 |
n | 4 |
n | 5 |
当n = 1时,开始出栈,先将参数(n = 1)出栈,以此类推。
通过上述操作,可以看出,执行递归操作所需要的内存空间和递归的深度成正比。纯粹的递归操作的空间复杂度是线性的,如果递归的深度为n,那么空间复杂度就是O(n)。