概论
时间复杂度和空间复杂度是算法中常用的衡量指标,用于评估算法的执行效率和资源消耗。
- 时间复杂度:是指算法执行所需要的时间量级,常用大O记法表示。
- 空间复杂度:是指算法执行所需的额外空间大小,也用大O记法表示。
时间复杂度
- 模块:不同量级有不同的速度,比如水 vs 水杯: 水
- 测试环境:在不同测试环境,速度也不同,比如手机 vs 电脑: 电脑
大O表示法
def tmp(n):
add =0
for i in range(n):
add +=1
return add
如上一个函数,假设代码一行运行时间是一个unit,那么总的运行时间:T(n) = (2n + 1) * unit,T(n) = O(f(n)) , O表示 T(n) 与 f(n) 成正比,O 表示渐近时间复杂度,表示代码执行时间随数据规模增长的变化趋势
当 n 很大时,低阶、常量、系数三部分并不左右增长趋势,所以都可以忽略.
就可以记为:T(n) = O(n); T(n) = O(n2)。
计算时间复杂度的原则
只关注循环次数多的代码
def tmp(n):
add = 0
for i in range(n):
add += i
return add
只关注循环,所以时间复杂度T(n) = O(n)
选大量级
def tmp(n):
for i in range(999):
print(123)
for i in range(n):
print(1)
for i in range(n):
for j in range(n):
print(2)
第一个循环时间复杂度O(999),第二个循环时间复杂度O(n),第三个循环时间复杂度O(n^2),所以这个函数的时间复杂度是O(n^2)
嵌套循环要乘积
def tmp(n):
for i in range(n):
a(i)
def a(n):
for i in range(n):
print('c')
tmp函数内部调用了函数a,所以tmp的时间复杂度是O(n^2)
常见复杂度分析
-
非多项式量级(过于低效) : O(2n) 和 O(n!)。
-
多项式量级:O(1), O(logn), O(n), O(nlogn), O(nk)
常数时间复杂度(O(1))
表示无论输入规模大小,执行时间都是恒定的。例如,对一个已知长度的列表进行索引操作。
a=2
b=3
d=4
线性时间复杂度(O(n),O(n+m))
表示随着输入规模增大,执行时间也呈线性增长。例如,对一个长度为n的列表进行遍历操作。
O(n)
def tmp(n):
add = 0
for i in range(n):
add += i
return add
O(m+n)
def tmp(m, n):
for i in range(m):
print(1)
for i in range(n):
print(2)
对数时间复杂度(O(log n))
表示执行时间随着输入规模增大而增加,但增幅逐渐减小。例如,二分查找算法。
def tmp(n):
i = 1
while i < n :
i = i * 2
i = 2^0,2^1, 2^2, 2^3…2^x
退出循环的条件是 : 2^x = n ,即 x = log2n,时间复杂度为 O(log2n)
def tmp(n):
i = 1
while i < n :
i = i * 3
log3n 就等于 log32 * log2n,所以 O(log3n) = O(C * log2n),其中 C=log32 是一个常量。基于我们前面的一个理论:在采用大 O 标记复杂度的时候,可以忽略系数,即 O(Cf(n)) = O(f(n))。所以,O(log2n) 就等于 O(log3n)。因此,在对数阶时间复杂度的表示方法里,我们忽略对数的“底”,统一表示为 O(logn)
平方时间复杂度(O(n^2),O(n*m))
表示执行时间与输入规模成平方关系增长。例如,嵌套循环遍历一个二维列表。
O(n^2)
def tmp(n):
for i in range(n):
for j in range(n):
print(2)
O(n*m)
def tmp(n,m):
for i in range(n):
for j in range(m):
print(1)
空间复杂度
- 渐进时间复杂度:表示算法的执行时间与数据规模之间的增长关系。
- 渐进空间复杂度:表示算法的存储空间与数据规模之间的增长关系。
常数空间复杂度(O(1))
表示算法执行所需的额外空间大小固定,与输入规模无关。例如,只使用有限的变量存储结果。
a = [1]
b = [2]
c = [3]
线性空间复杂度(O(n))
表示算法执行所需的额外空间大小随着输入规模线性增长。例如,使用一个长度为n的列表存储中间结果。
def tmp(n):
a = [1]*n
for i in a:
print(i)