跳到主要内容

算法复杂度分析

算法复杂度分析用于衡量算法随输入规模增长所需的资源(时间与空间),是评估算法效率的核心工具。掌握大 O 表示法有助于在编码前预判程序性能,避免在数据规模扩大时出现指数级退化。

时间与空间复杂度

时间复杂度 描述算法执行步数随输入规模 n 的增长趋势;空间复杂度 描述算法在运行过程中占用的额外存储。两者通常使用大 O 表示法,只保留最高阶项并忽略常数系数,例如 3n² + 2n + 1 记为 O(n²)

最好、最坏与平均情况

同一算法在不同输入下表现可能差异巨大,常以三种情况描述:

  • 最好情况:输入最优时的复杂度,例如有序数组的线性查找为 O(1)
  • 最坏情况:输入最差时的上界,常作为算法性能的保证,例如快速排序最坏为 O(n²)
  • 平均情况:在输入分布上的期望复杂度,常用随机化或概率分析推导,例如快速排序平均为 O(n log n)

均摊分析(amortized analysis)用于将少数高代价操作的耗时分摊到多次低代价操作上,例如动态数组 append 偶尔扩容为 O(n),但整体均摊为 O(1)

常见复杂度级别

按增长速度快慢排列,前者在规模增大时优势越明显:

级别名称典型场景
O(1)常数哈希表查找、数组按下标访问
O(log n)对数二分查找、平衡 BST 查询
O(n)线性数组遍历、线性查找
O(n log n)线性对数归并排序、快速排序平均
O(n²)平方冒泡排序、选择排序、嵌套循环

复杂度从 O(log n)O(n²) 看似只差几个量级,当 n = 10⁶ 时,前者仅需约 20 次操作,后者却高达 10¹² 次,实际运行时天差地别。

分析示例

def sum_pairs(arr):
n = len(arr) # O(1)
total = 0 # O(1)
for x in arr: # 循环 n 次
total += x # O(1)
return total # 整体 O(n)

def has_duplicate(arr):
for i in range(len(arr)): # 外层 n
for j in range(i + 1, len(arr)): # 内层最多 n
if arr[i] == arr[j]: # O(1)
return True
return False # 整体 O(n²)

第一段为线性扫描,第二段双重循环实现重复检测,后者在大规模数据下需改用哈希表 O(n) 方案。复杂度分析的目标,是在写代码时主动选择更优的结构,让程序在数据增长时仍保持可控。