一、复杂度基本知识
1. 定义
- 在进行算法分析时,语句总的执行次数T(n)是关于问题规模 n 的函数,进而分析T(n)随 n 的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间度量,记作:T(n) = O(f(n))。它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的监禁时间复杂度,简称时间复杂度。其中f(n)是问题规模n的某个函数。
- 复杂度也叫渐进复杂度,包括时间复杂度和空间复杂度,用来分析算法执行效率与数据规模之间的增长关系,可以粗略地表示,越高阶复杂度的算法,执行效率越低。
- 复杂度描述的是算法执行时间或占用内存空间随数据规模的增长关系。
- 用途:
- 衡量程序的运行效率
2. 复杂度分类
- 时间复杂度
- 平均时间复杂度
- 最坏时间复杂度
- 空间复杂度
- 计算公式:S(n) = O(f(n)),n为问题的规模,f(n)为语句关于 n 所占存储空间的函数
- 算法在运行过程中临时占用空间大小的量度
3. 记法
- 用大写的0()来体现算法时间复杂的的记法,称为大O记法。
- 常见阶数:
- 常数阶:O(1)
# 代码执行消耗时间不随变量增长 a = 1 b = 2 res = a + b
- 线性阶:O(n)
for i in range(n): # 消耗时间随n的变化而变化 res += i
- 对数阶:O(logN)
i = 1 while i < n: i *= 2
- nlogN阶:O(nlogN)
for i in range(1, n): j = 1 while j < n: j *= 2
- 平方阶:O(n^2)
for i in range(n): for j in range(n): res = i * j
- 对数阶:O(2^n)
def fibonacci(n): return fibonacci(n-2) + fibonacci(n-1)
- 常数阶:O(1)
- 推导方法
- 用常数 1 取代运行时间中的所有加法常数
- 在修改后的运行次数函数中,只保留最高阶项
- 如果最高阶项存在且不是1,则去除这个阶的常数(复杂度与常系数无关)
- 常用判断方法
- 一个顺序结构的代码,时间复杂度是 O(1)
- 一个简单的 for 循环,时间复杂度是 O(n)
- 两个顺序执行的 for 循环,时间复杂度是 O(n)+O(n)=O(2n),其实也是 O(n)
- 两个嵌套的 for 循环,时间复杂度是 O(n²)
- 二分查找,时间复杂度都是 O(logn)
3. 常见算法复杂度
- 常见数据结构复杂度
- 排序复杂度
- 图
- 堆