对于 时间复杂度和空间复杂度分析

基本概念

1. 时间复杂度(Time Complexity)

  • 衡量算法运行时间随输入规模增长的变化趋势。
  • 不关注具体运行时间(如秒),而是关注操作次数的增长率。
  • 使用大O记号(Big O Notation) 表示上界。

2. 空间复杂度(Space Complexity)

  • 衡量算法所需内存空间随输入规模增长的变化趋势。
  • 包括:
    • 输入数据占用的空间(通常不计入)
    • 辅助空间(算法额外使用的变量、递归栈、临时数组等)

常见的复杂度类型

复杂度 名称 增长速度
O(1) 常数时间 最快,与 n 无关
O(log n) 对数时间 非常高效(如二分查找)
O(n) 线性时间 常见于单层循环
O(n log n) 线性对数 高效排序算法(如归并、快排平均)
O(n²) 平方时间 双重循环,小规模可用
O(2ⁿ) 指数时间 组合爆炸,仅适用于极小 n
O(n!) 阶乘时间 极慢(如暴力解旅行商问题)

分辨方式

第1步:确定输入规模 n

  • 找出影响运行时间的主要变量。
  • 常见情况:
    • 数组长度 → n = len(arr)
    • 字符串长度 → n = len(s)
    • 矩阵大小 → n = rows × cols 或分别用 m, n
    • 树的节点数 → n = number of nodes

📌 注意 :如果有多个变量(如两个数组长度分别为 m 和 n),保留两者,不要强行合并。

第2步:找出"基本操作"并数执行次数

基本操作通常是:

  • 比较(if a > b)
  • 赋值(x = y)
  • 算术运算(i + 1)
  • 函数调用(若内部复杂度已知)

重点看循环和递归!

情况1:单层循环

python 复制代码
for i in range(n):
    print(i)

→ 循环体执行 n 次 → O(n)

情况2:嵌套循环

python 复制代码
for i in range(n):
    for j in range(n):
        do_something()  # O(1)

→ 内层执行 n 次,外层也 n 次 → 总共 n × n = n² → O(n²)

🔍 变种:内层依赖外层

python 复制代码
for i in range(n):
    for j in range(i):  # j 从 0 到 i-1
        ...

总次数 = 0 + 1 + 2 + ... + (n−1) = n(n−1)/2 ≈ n²/2 → O(n²)(忽略常数)

情况3:对数循环(每次减半)

python 复制代码
while n > 1:
    n //= 2

→ 循环次数 = log₂n → O(log n)

情况4:多个独立循环

python 复制代码
for i in range(n): ...      # O(n)
for i in range(n): ...      # O(n)

总时间 = O(n) + O(n) = O(n)(加法取最大项)

第3步:处理递归

写递推式,再估算。

方法A:展开法(适合简单递归)

python 复制代码
def f(n):
    if n <= 1: return 1
    return f(n-1) + 1
  • T(n) = T(n−1) + O(1)
  • 展开:T(n) = T(n−2) + 2 = ... = T(0) + n → O(n)

方法B:主定理(Master Theorem)------用于分治

适用于形如:
T(n) = a·T(n/b) + f(n)

常见例子:

  • 归并排序:T(n) = 2T(n/2) + O(n) → O(n log n)
  • 二分查找:T(n) = T(n/2) + O(1) → O(log n)

💡 主定理速记:

  • 若 f(n) = O(n^c),比较 c 与 log_b(a)
  • c < log_b(a) → T(n) = O(n^{log_b a})
  • c = log_b(a) → T(n) = O(n^c log n)
  • c > log_b(a) → T(n) = O(f(n))

第4步:简化表达式(大O规则)

  • 去掉常数:5n → n
  • 去掉低阶项:n² + n + 100 → n²
  • 多变量保留:O(m + n)、O(mn)

估算空间复杂度的步骤

第1步:区分"输入空间"和"额外空间"

  • 输入数组、字符串等不算在空间复杂度中。
  • 只算算法自己申请的内存。

第2步:检查以下来源

来源 是否计入 示例
局部变量 是(但通常 O(1)) int x = 0
新建数组/哈希表 是 seen = [False]*n → O(n)
递归调用栈 是 递归深度 d → O(d)
返回结果 通常不算(除非题目特别说明) LeetCode 中返回数组一般不计入

第3步:典型场景

  • 迭代算法(无递归、无额外结构)→ O(1)
  • 使用哈希表记录元素 → O(n)
  • 递归深度为 n(如链表递归)→ O(n)
  • 平衡树递归(如BST)→ O(log n)

快速估算口诀(面试可用)

结构 时间复杂度 空间复杂度
单层 for/while O(n) O(1)
双重嵌套循环 O(n²) O(1)
二分查找 O(log n) O(1)(迭代)或 O(log n)(递归)
归并/快排 O(n log n) O(n)(归并)或 O(log n)(快排平均)
DFS/BFS(图/树) O(V + E) O(V)(栈/队列+visited)
动态规划(一维) O(n) O(n) 或 O(1)(滚动数组)
相关推荐
行百里er7 小时前
Redis 完结篇——Redis 热点问题在 Spring Boot 项目中实战
redis·后端
高频因子挖掘机8 小时前
只取最近 60 个交易日,却每次拉全历史:量化脚本变慢的原因与改法
后端·github·api
孟健9 小时前
从5000亿Token到83%字节匹配:AI逆向工程与重构的工程闭环实践
后端·架构·ai编程
码事漫谈10 小时前
丢得静悄悄,谈一谈 Agent 的记忆是怎么没的
后端
迪飞特科技10 小时前
智慧物业平台实战:Spring Boot 整合小程序实现报修巡检费用全流程
spring boot·后端·小程序
考虑考虑10 小时前
@JsonInclude注解使用
spring boot·后端·spring
IT_陈寒10 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端
网易云信10 小时前
大模型能上岗做销售吗?我们让 12 款国产模型交了 420 份作业
前端·后端
CCblandy10 小时前
HTTP 长连接 3 类故障实测:[WinError 10053]、99 个 TIME_WAIT、69 次多余握手,4 种对策怎么选
后端·python·网络协议·http·云原生·性能优化·架构
蜗牛互联网10 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python