1. 什么是大 O 复杂度?如何推导?

大 O:描述算法运行时间随输入规模 n 增长的量级趋势(渐进上界)。忽略常数和低阶项。

推导三步:

  1. 只关注最高阶项:3n² + 5n + 8 → O(n²)
  2. 忽略系数:2n → O(n)
  3. 循环嵌套相乘、顺序相加:两层循环 O(n²),先 O(n) 后 O(n) 还是 O(n)

常见复杂度排序(快→慢):

O(1) < O(log n) < O(√n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2ⁿ) < O(n!)

🎯 面试要点

  • 判断循环:for (i=1; i<n; i*=2) → O(log n);两层独立循环 → O(n·m) 或 O(n²)
  • 面试讲复杂度要讲最坏情况(除非题目要求均摊/平均)
  • Hash 操作均摊 O(1),最坏 O(n)(大量冲突)——答"均摊 O(1)"更严谨

2. 递归算法的复杂度怎么算?

方法:递归树或 Master 定理。关键看每层调用数 × 每层工作量:

🎯 面试要点

  • 记忆化搜索 = 递归 + 缓存:时间 = 状态数 × 每状态耗时(DP 复杂度分析的口径)
  • 回溯的复杂度:解空间大小 × 每解构造成本——答"最坏 O(2ⁿ·n)"这类才严谨

3. 空间复杂度分析要点?

🎯 面试要点

  • "额外空间 O(1)"与"总空间"要分清楚,面试官常抠这个
  • 能原地就原地(如双指针原地去重),空间优化是加分动作

🎤 常见面试追问

  1. 怎么快速判断一段代码的时间复杂度?——数循环层数:一层 O(n)、两层嵌套 O(n²);循环内每次减半 O(log n);递归看"调用树"。
  2. O(n) 和 O(log n) 谁快?——大 O 看趋势:n 很大时 log n 远小于 n(100 万的对数只有 20)。但常数项可能让 O(n) 的实际代码更快(如哈希表均摊 O(1) vs 红黑树 O(log n) 都是"快")。
  3. 递归复杂度怎么算?——主定理(Master):T(n)=aT(n/b)+f(n) 套三种情况;或画递归树数节点数 × 每层工作量。
  4. "均摊 O(1)"是什么意思?——单次操作可能 O(n)(如 ArrayList 扩容),但平均到每次操作是 O(1)。说"均摊"比说"O(1)"严谨。
  5. 空间复杂度只算额外空间吗?——面试惯例:输入数组不算额外空间,只说算法"额外开辟"的(辅助数组、递归栈深度)。

📖 名词解释(本页术语)

术语 大白话解释
大 O 记号描述算法性能随数据量增长的"量级趋势",忽略常数和低阶项。O(n²) 表示"数据翻倍,时间变 4 倍"。
时间复杂度运行时间随输入规模增长的度量(不是具体秒数)。
空间复杂度内存占用随输入规模增长的度量(O(1) 原地 / O(n) 额外数组)。
递归树把递归调用画成一棵树,数"节点数 × 每节点工作量"来算复杂度。如二分 T(n)=T(n/2)+O(1):递归树高 log n、每层 1 个节点 → O(log n);
归并 T(n)=2T(n/2)+O(n):每层总工作量 O(n) × 高 log n → O(n log n)。
Master 定理(主定理)解分治递推式 T(n)=aT(n/b)+f(n) 的公式:比较 f(n) 和 n^log_b(a) 的大小关系确定复杂度。
均摊复杂度把偶尔一次的高成本操作"平均"到每次操作上。如 ArrayList 扩容:偶尔 O(n),均摊 O(1)。
最坏/平均/最好复杂度同一算法在不同输入下的表现:快排最好 O(n log n)、最坏 O(n²)(已有序)。面试默认讲最坏。
原地算法(in-place)几乎不额外开内存的算法(O(1) 辅助空间),如原地快排、双指针去重。
⚠️ 本页面由 AI 生成,内容仅供参考,请以官方文档和实际源码为准。