0 · 对数换底、等比级数与递归树:3 分钟找回算法复杂度直觉
- 对数公式(折半次数的来源):若每次规模除以 \(b\),经过 \(k\) 层后规模变为 \(n/b^k = 1 \iff k = \log_b n\)。换底公式:\(\log_a n = \dfrac{\log_b n}{\log_b a}\),相差仅常数倍,故大 \(O\) 记号中底数可省写为 \(O(\log n)\)。记住重要恒等式:\(a^{\log_b n} = n^{\log_b a}\)(这是递归树第 \(k=\log_b n\) 层叶子总数等于 \(n^{\log_b a}\) 的代数原因!)。
- 主定理 \(T(n) = aT(n/b) + f(n)\) 的本质是“整棵递归树等比求和谁占大头”:设深度 \(L=\log_b n\),第 \(j\) 层有 \(a^j\) 个子问题,每个开销 \(f(n/b^j)\)。比较叶子层总开销 \(n^{\log_b a}\) 与根节点分裂合并开销 \(f(n)\):
- 若 \(f(n) = O(n^{\log_b a - \varepsilon})\)(上轻下重,公比 \(>1\)):叶子层占主导,\(T(n) = \Theta(n^{\log_b a})\);
- 若 \(f(n) = \Theta(n^{\log_b a}\log^k n)\)(上下均势,每层开销同阶):共 \(\log n\) 层累加,\(T(n) = \Theta(n^{\log_b a}\log^{k+1} n)\);
- 若 \(f(n) = \Omega(n^{\log_b a + \varepsilon})\) 且满足正则条件 \(af(n/b)\le cf(n)\ (c<1)\)(上重下轻,公比 \(<1\)):根层占主导,\(T(n) = \Theta(f(n))\)。
自学起点 · 从遗忘基础到考试答题
先补的数学
对数解决“反复折半”的层数问题:n 连续减半,约 log₂n 次到 1;等差求和 1+⋯+n=n(n+1)/2;递归树 T(n)=2T(n/2)+n 的每层工作量为 n,共约 log₂n 层,因此 Θ(n log n)。
手算例题 · 二分搜索
有序数组 [1,3,5,8,10] 查找 8。先看索引 2,值 5,小于 8,目标只能在右半边;再看索引 3,值 8,找到。循环始终保持“若目标存在,它在当前搜索区间”的不变式。迭代时间 O(log n),额外空间 O(1)。
💡 破题关键与第一步提示(遮答案自测用 · 考前自测:快速排序为何不是任何输入都 O(n log n)?)
破题切入点:划分均匀时递归深度约 log n;总是选到极端划分元时 T(n)=T(n−1)+Θ(n)=Θ(n²)。(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(考前自测:快速排序为何不是任何输入都 O(n log n)?)
划分均匀时递归深度约 log n;总是选到极端划分元时 T(n)=T(n−1)+Θ(n)=Θ(n²)。区分最坏、平均与最好复杂度。
考试演算:归并排序递推式为什么是 \(\Theta(n\log n)\)?
题型:给出一个规模 \(n\) 的问题,每次分成两个规模 \(n/2\) 的子问题,划分与合并耗时 \(\Theta(n)\)。写递推式、求复杂度并解释。
- 列式:\(T(n)=2T(n/2)+cn\),且 \(T(1)=\Theta(1)\)。
- 逐层展开:第 \(i\) 层有 \(2^i\) 个规模 \(n/2^i\) 的子问题,合并总代价 \(2^i c(n/2^i)=cn\)。
- 层数:经过 \(\log_2n\) 次折半规模达到 1,共 \(\Theta(\log n)\) 个非叶层;各层总成本为 \(n\log_2n\),叶层总成本为 \(\Theta(n)\)。
- 结论:\(T(n)=\Theta(n\log n)\)。由主定理 \(a=b=2\),\(n^{\log_ba}=n\),属于第二情形。
💡 破题关键与第一步提示(遮答案自测用 · 自己做:\(T(n)=3T(n/2)+n\)(假设 \(n=2^k\)))
破题切入点:\(n^{\log_2 3}\) 比 \(n\) 增长更快,满足主定理第一情形,故 \(T(n)=\Theta(n^{\log_2 3})\)。(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(自己做:\(T(n)=3T(n/2)+n\)(假设 \(n=2^k\)))
\(n^{\log_2 3}\) 比 \(n\) 增长更快,满足主定理第一情形,故 \(T(n)=\Theta(n^{\log_2 3})\)。考试时写明 \(a=3,b=2,f(n)=n\)。
Python 衔接:二分查找用 left, right 维持闭区间不变式;若返回第一次出现的位置,条件分支要单独处理重复值,不能把“找任意一个”和“找最左侧”写成同一个解。
先看:本模块易错点与补充
理论校准- 大 O 是某类运行时间的渐近上界,不自动代表“最坏时间”。比较两个增长率应用
f(n)=o(g(n)),不要写 O 集合的“小于”。 - 比较排序的
Ω(n log n)下界与非比较排序不可混淆;固定主元快排在特殊输入下会退化。 - 二分与归并的 Python 版本和可执行测试见 Python 求职衔接。
0 · 课程与考核
| 项目 | 内容(两届课件略有出入,以当年通知为准) |
|---|---|
| 学时 / 教师 | 32 学时;刘瑶老师(沙河主楼中 427) |
| 成绩构成 | CH01 版:课堂参与 20% + 课程报告/讲座 30% + 期末 50%;Review 版:平时 60% + 期末开卷 40%。缺席 4 次以上没有平时成绩 |
| 期末题型(Review 版) | 选择 20% + 判断 20% + 填空 30%(含算法填空)+ 问答 10%(复杂度分析)+ 算法设计 20% |
| 期末题型(2021 大纲版) | 判断 10 题(20 分)+ 简单计算 20–30 分(渐进式 / 贪心 / 分治递归式 / DP / 最大流最小割 / NPC 证明 2–3 题 / 近似) |
| 复习主线 | 复习资料/2021年复习大纲.pptx(16 页 = 全部考点)+ Review-v2.pptx(知识点浓缩 + 例题) |
- 渐近符号与阶排序——判断/选择高频:O/Ω/Θ 定义辨析、把 n, log n, n log n, n², 2ⁿ, n! 从小到大排序;
- 机器提速经典题——"机器快 64 倍/100 倍能多处理多大规模"(本模块例 1、例 2 两种皮肤都要会,历年反复出现);
- 递归式求解——Master 定理三情形 + 特征方程法(填空/计算,"典型题 · 解递推关系"是模板);
- 分治适用四条件与递归三要素——判断/简答;
- Hanoi / 全排列 / 整数划分——算法填空递归代码或写递归式。
数学手生?增长率比较(对数<幂<指数)、求和公式、矩阵运算的"三分钟复习"在上级目录 《数学基础工具箱》第 3、4、5 节;考前看第 8 节"急救包"。
1 · 算法是什么
算法 vs 程序:程序是算法用某种程序设计语言的具体实现;算法的有穷性意味着不是所有程序都是算法(如操作系统死循环)——这是判断题高频点。
算法分类:数值型算法(基本运算为算术运算)与非数值型算法。算法与数据结构的关系:算法 + 数据结构 = 程序;数据的逻辑结构与存储结构共同决定实现方式。
2 · 复杂性计量与渐近符号
复杂性 = 时间复杂性 + 空间复杂性。同一算法运行时间受硬件、语言、输入数据影响,所以只比较增长趋势:
| 记号 | 定义 | 含义 |
|---|---|---|
| \(f(N)=O(g(N))\) | ∃ 正常数 \(c, n_0\),∀\(n\ge n_0\): \(|f(N)|\le c|g(N)|\) | g 是 f 的上界(阶不高于 g) |
| \(f(N)=\Omega(g(N))\) | ∃ \(c, n_0\): \(|f(N)|\ge c|g(N)|\) | g 是 f 的下界 |
| \(f(N)=\Theta(g(N))\) | ∃ \(c_1,c_2,n_0\): \(c_1 g\le|f|\le c_2 g\) | 同阶(= O 且 = Ω) |
复杂性层次:\(1\prec\log n\prec n\prec n\log n\prec n^2\prec n^3\prec\dots\prec2^n\prec n!\)(按渐近增长快慢排序,\(f\prec g\) 表示 \(f=o(g)\))。多项式时间算法(n 在底数位置)被视为“可解”;指数/阶乘级(n 在指数上)被认为不可承受。
3 · 分析法则与常见函数阶
- 多项式:\(a_0+a_1n+\cdots+a_dn^d=\Theta(n^d)\)(\(a_d>0\));
- 对数换底:\(\log_a n=O(\log_b n)\)(底数不重要,都是 \(\Theta(\log n)\));对任意 \(a>0\):\(\log n=o(n^a)\)(对数永远慢于任意正幂);
- 指数碾压:\(n^b=o(a^n)\)(\(a>1\));\(n^{100}=o(1.01^n)\)(最终);
- 取整:\(\lfloor n/2\rfloor+\lceil n/2\rceil=n\),\(\lceil\lceil n/a\rceil/b\rceil=\lceil n/(ab)\rceil\)\;\text{(a,b 为正整数)};
- Stirling:\(n!\approx\sqrt{2\pi n}\,(n/e)^n\)。
💡 破题关键与第一步提示(遮答案自测用 · 解答)
破题切入点:\(2 \prec \log n \prec n^{2/3} \prec 20n \prec 4n^2 \prec 3^n \prec n! \cdots\)(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(解答)
4 · 经典计算题:机器提速问题 ★(历年必考原型)
💡 破题关键与第一步提示(遮答案自测用 · 解答)
破题切入点:\(3\cdot 2^{n_1}=64\cdot 3\cdot 2^n\Rightarrow 2^{n_1}=2^{n+6}\Rightarrow n_1=n+6\)——指数时间算法提速只多解 6 个规模!(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(解答)
💡 破题关键与第一步提示(遮答案自测用 · 解答(课件标准答案))
破题切入点:① \(n'=100n\);② \(n'^2=100n^2\Rightarrow n'=10n\);(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(解答(课件标准答案))
💡 破题关键与第一步提示(遮答案自测用 · 解答)
破题切入点:\(n^3=3.6\times10^6\Rightarrow n\approx153\);(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(解答)
5 · 递归:概念与四大例题
三种适用场景:问题定义是递归的(阶乘、Fibonacci);数据结构是递归的(二叉树遍历);求解过程是递归的(Hanoi、全排列)。
6 · 分治法:思想与适用条件
关键推论:满足①②而不满足③ → 考虑贪心或动态规划;满足①②③但④不成立(子问题重叠)→ 动态规划。
7 · Master 定理 ★★(大题必考)
- 若 \(f(n)=O\big(n^{E-\varepsilon}\big)\)(f 多项式地慢),则 \(T(n)=\Theta\big(n^{E}\big)\);
- 若 \(f(n)=\Theta\big(n^{E}\big)\)(同阶),则 \(T(n)=\Theta\big(n^{E}\log n\big)\);
- 若 \(f(n)=\Omega\big(n^{E+\varepsilon}\big)\)(f 多项式地快),且对某 \(c<1\) 充分大有 \(a f(n/b)\le c f(n)\),则 \(T(n)=\Theta\big(f(n)\big)\)。
| 算法 | 递归式 | 结论 |
|---|---|---|
| 二分搜索 | \(T(n)=T(n/2)+O(1)\) | \(\Theta(\log n)\)(a=1,b=2,E=0,情形1/2边界) |
| 合并排序 | \(T(n)=2T(n/2)+O(n)\) | \(\Theta(n\log n)\)(情形2) |
| Strassen | \(T(n)=7T(n/2)+\Theta(n^2)\) | \(\Theta(n^{\log_2 7})\approx\Theta(n^{2.81})\)(情形1) |
| 普通矩阵乘 | \(T(n)=8T(n/2)+\Theta(n^2)\) | \(\Theta(n^3)\)(情形1) |
| 最接近点对 | \(T(n)=2T(n/2)+O(n)\) | \(\Theta(n\log n)\)(情形2) |
| 棋盘覆盖 | \(T(k)=4T(k-1)+O(1)\) | \(\Theta(4^k)\)(n=2ᵏ 时即 Θ(n²) 个骨牌) |
💡 破题关键与第一步提示(遮答案自测用 · 解答)
破题切入点:\(X(n)=X(n/3^k)+k=1+\log_3 n\)。(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(解答)
8 · 分治六大经典算法
8.1 二分搜索
已排序数组取中间元素比较,每次规模减半。最坏 while 执行 O(log n) 次、每次 O(1) → O(log n)。变体题(作业):x 不在数组中时返回小于 x 的最大位置 i 与大于 x 的最小位置 j。
8.2 大整数乘法
朴素 \(O(n^2)\)。分治 \(X=a\cdot2^{n/2}+b,\ Y=c\cdot2^{n/2}+d\):直接拆要 4 次子乘法;改进为 \[XY=ac\cdot2^n+\big[(a+b)(c+d)-ac-bd\big]2^{n/2}+bd\] 只需 3 次子乘法:\(T(n)=3T(n/2)+O(n)=\Theta(n^{\log_2 3})\approx O(n^{1.59})\)。思想:降低复杂度的关键是减少子乘法次数(判断题:不是减少加法)。
8.3 Strassen 矩阵乘法
分块后同样从 8 次子块乘法降到 7 次(Strassen 的 7 个中间矩阵 M1–M7):\(T(n)=7T(n/2)+\Theta(n^2)=\Theta(n^{\log_2 7})\approx n^{2.81}\)。已证明 2×2 矩阵 7 次乘法是必要的;当前还有渐近更快的矩阵乘法算法,但具体理论指数会随研究进展变化;课堂重点是 Strassen 的 \(\log_2 7\)。
8.4 棋盘覆盖
\(2^k\times2^k\) 棋盘恰有一特殊方格,用 L 型骨牌覆盖其余。分治:十字中心放置一块 L 骨牌(不含特殊方格的三个象限各占一格),把问题化为 4 个 \(2^{k-1}\) 子棋盘。骨牌数 \((4^k-1)/3\),时间 \(\Theta(4^k)\)。作业常考完整实现。
8.5 快速排序 ★
8.6 线性时间选择 ★
RandomizedSelect(期望 O(n)):随机划分元,只递归进入包含第 k 小的一侧(对比快排两侧都递归)。
Select(最坏 O(n),中位数的中位数):① n 个元素按 5 个一组排序,取出各组中位数(共 ⌈n/5⌉ 个);② 递归求这些中位数的中位数 x;③ 用 x 划分。关键不等式:x 至少比 \(3\lfloor(n-5)/10\rfloor\) 个元素大(和小),子问题规模 ≤ \(3n/4\),而 \(n/5+3n/4=19n/20=0.95n=\varepsilon n\)——两递归自变量之和按常数比例收缩,故 \(T(n)=O(n)\)。分组大小 5 与阈值 75 是关键(判断/填空点)。
8.7 最接近点对
一维:排序后中位数 m 分两半,递归得 d₁,d₂,d=min;合并时只需检查 (m−d, m] 与 (m, m+d] 两段——每段至多 1 个点。
二维:垂直线 x=m 分割;合并时只需检查宽 2d 的带状区。带内点按 y 排序,按 y 顺序对每个点检查其后至多 7 个候选点(经典条带打包论证给出常数上界;各半区内已知最小距离至少 d,不能仅用“分成六块”替代严谨证明)。合并 O(n): \[T(n)=2T(n/2)+O(n)=O(n\log n).\] 朴素两两比较是 O(n²)——分治收益巨大。∎
8.8 循环赛日程表
n=2ᵏ 个选手,每选手与其他 n−1 人各赛一次、每天至多一场,共 n−1 天。分治填表:左上角(前半选手前半程)→ 左下 = 左上 + \(2^{k-1}\) → 右上 = 左下 → 右下 = 左上。8 人日程表是问答真题(Review S107)。
📄 期末禁止写代码:分治法经典算法(二分查找 / 归并排序 / 线性时间选择) · 自然语言标准作答四步模板
- ① 状态/子问题定义与符号声明:设原输入规模为 \(n\),子问题区间为 \([low, high]\);归并排序将数组均分为左右两半,线性选择以主元 \(pivot\) 划分为小于、等于、大于三个子集。
- ② 核心递推方程 / 贪心策略 / 搜索剪枝准则:归并排序满足 \(T(n)=2T(n/2)+O(n)\);二分查找满足 \(T(n)=T(n/2)+O(1)\);五元中位数线性选择满足 \(T(n)\le T(\lceil n/5\rceil)+T(7n/10+6)+O(n)\)。
- ③ 算法自然语言分步流程(严禁贴 C/Python 语法):第一步(Divide):计算中点或选定主元划分数组;第二步(Conquer):递归求解子区间(二分查找与线性选择仅递归进入含目标的单一分支);第三步(Combine):双指针线性合并两个有序子数组(二分与选择无需合并步)。
- ④ 时间与空间复杂度严格推导:由 Master 定理,归并排序 \(a=2,b=2,f(n)=\Theta(n)=\Theta(n^{\log_b a})\) 属情形 2,时间 \(O(n\log n)\)、空间 \(O(n)\);二分查找时间 \(O(\log n)\);线性选择最坏/平均时间 \(O(n)\)。
🐍 Python 求职机试标准实现(源自 practice_algorithms.html · 在线阅读器)
def lower_bound(nums, target):
"""已排序 nums 的第一个 >= target 的下标。O(log n) 时间。"""
lo, hi = 0, len(nums)
while lo < hi:
mid = (lo + hi) // 2
if nums[mid] < target:
lo = mid + 1
else:
hi = mid
return lo
def merge_sort(nums):
"""稳定归并排序。O(n log n) 时间、O(n) 额外空间。"""
if len(nums) < 2:
return list(nums)
mid = len(nums) // 2
a, b = merge_sort(nums[:mid]), merge_sort(nums[mid:])
i = j = 0
out = []
while i < len(a) and j < len(b):
if a[i] <= b[j]:
out.append(a[i])
i += 1
else:
out.append(b[j])
j += 1
return out + a[i:] + b[j:]
def quick_select(nums, k):
"""三路划分求 0-indexed 第 k 小元素。平均 O(n) 时间。"""
if not 0 <= k < len(nums):
raise ValueError('k 越界')
arr = list(nums)
while True:
pivot = arr[len(arr) // 2]
lt = [x for x in arr if x < pivot]
eq = [x for x in arr if x == pivot]
gt = [x for x in arr if x > pivot]
if k < len(lt):
arr = lt
elif k < len(lt) + len(eq):
return pivot
else:
k -= len(lt) + len(eq)
arr = gt
补齐历史大纲重点:逆序对计数 Counting Inversions
来源:仓库 复习资料/2021年算法设计与分析复习大纲.pptx 第 4 页明确列出;是 2021 年旧大纲要求,不代表已确认 2026 年考核范围。
题意:在数组中统计满足 \((i,j):i<j,\;a_i>a_j\) 的下标对总数。例如 [2,4,1,3,5] 中共有三对:(2,1)、(4,1)、(4,3),答案为 3。
- 分:拆成左半与右半;逆序对分为全左、全右、横跨左右三类,互不重叠且覆盖全部情况。
- 治:递归得到左右排序结果和各自内部的逆序对数。
- 合:归并时若 \(L_i\le R_j\),先取左元素,不产生新的跨区逆序对;若 \(L_i>R_j\),由于左半段已排序,从当前
i到左半末尾的所有元素都大于 \(R_j\),一次性累加 \(|L|-i\)。 - 复杂度:合并 O(n),递推 \(T(n)=2T(n/2)+\Theta(n)=\Theta(n\log n)\),与暴力枚举的 O(n²) 对比。
💡 破题关键与第一步提示(遮答案自测用 · 展开 Python 参考实现(面试代码;考试按老师要求描述思想))
破题切入点:def inversion_count(nums): def solve(a): if len(a) <= 1: return a, 0 m = len(a) // 2 left, c(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(展开 Python 参考实现(面试代码;考试按老师要求描述思想))
def inversion_count(nums):
def solve(a):
if len(a) <= 1:
return a, 0
m = len(a) // 2
left, cnt_l = solve(a[:m])
right, cnt_r = solve(a[m:])
i = j = 0
merged = []
count = cnt_l + cnt_r
while i < len(left) and j < len(right):
if left[i] <= right[j]:
merged.append(left[i])
i += 1
else:
count += len(left) - i
merged.append(right[j])
j += 1
merged.extend(left[i:])
merged.extend(right[j:])
return merged, count
return solve(nums)[1]
assert inversion_count([2, 4, 1, 3, 5]) == 3
assert inversion_count([1, 1, 1]) == 0
assert inversion_count([3, 2, 1]) == 3
注意 <= 是刻意使用的:相等值不是逆序对,别因比较符号写错多计。
💡 破题关键与第一步提示(遮答案自测用 · 自测:数组 [3,1,2,1] 有多少个逆序对?)
破题切入点:答案 4:3>1、3>2、3>1、2>1。(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(自测:数组 [3,1,2,1] 有多少个逆序对?)
答案 4:3>1、3>2、3>1、2>1。两个相等的 1 不构成逆序对。
📄 期末禁止写代码:分治统计逆序对(Counting Inversions) · 自然语言标准作答四步模板
- ① 状态/子问题定义与符号声明:设数组 \(A[1..n]\),逆序对定义为满足 \(i
A[j]\) 的二元组。将其拆分为左半内部逆序对、右半内部逆序对、以及跨越中点 \(mid\) 的逆序对三部分。 - ② 核心递推方程 / 贪心策略 / 搜索剪枝准则:归并左右两个已排序子数组 \(L\) 与 \(R\) 时,若当前指针处 \(L[i] \le R[j]\) 则无新增跨区逆序对;若 \(L[i] > R[j]\),则 \(L[i..|L|]\) 全部大于 \(R[j]\),一次性累加跨区逆序对数 \(|L|-i+1\)。
- ③ 算法自然语言分步流程(严禁贴 C/Python 语法):第一步:若区间长度 \(\le 1\) 直接返回 0;第二步:以中点 \(mid\) 递归统计左半得 \(c_1\)、右半得 \(c_2\) 并各自排好序;第三步:用双指针线性归并左右有序表并同步累加跨区逆序对 \(c_3\),返回 \(c_1+c_2+c_3\)。
- ④ 时间与空间复杂度严格推导:递归方程 \(T(n)=2T(n/2)+\Theta(n)\),由 Master 定理情形 2 得时间复杂度 \(\Theta(n\log n)\),辅助归并数组空间复杂度 \(\Theta(n)\)。
🐍 Python 求职机试标准实现(源自 practice_algorithms.html · 在线阅读器)
def count_inversions(nums):
"""归并分治统计逆序对总数 (i < j 且 nums[i] > nums[j])。O(n log n) 时间。"""
def sort_count(arr):
if len(arr) < 2:
return list(arr), 0
mid = len(arr) // 2
left, c1 = sort_count(arr[:mid])
right, c2 = sort_count(arr[mid:])
merged, cross, i, j = [], 0, 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
merged.append(left[i])
i += 1
else:
merged.append(right[j])
cross += len(left) - i
j += 1
merged.extend(left[i:])
merged.extend(right[j:])
return merged, c1 + c2 + cross
_, total = sort_count(nums)
return total
9 · 公式速查(一页纸素材)
| 渐近符号 | O 上界 / Ω 下界 / Θ 同阶;最优算法 = 达到下界 Ω(f) 的 O(f) 算法 |
| 层次 | 1 ≺ log n ≺ nᵃ ≺ 多项式 ≺ 指数 ≺ n!;log n = o(nᵃ);n^b = o(aⁿ) |
| 分析法则 | 循环=体×次数;顺序相加;if-else 取 max |
| Master | \(T(n)=aT(n/b)+f\): 比较 f 与 \(n^{\log_b a}\) → 三情形(nᴱ / nᴱlog n / f(n)) |
| 递归经典 | Hanoi \(2^n-1\);Fib 递归 O(2ⁿ) / 递推 O(n);棋盘覆盖 \(\Theta(4^k)\) |
| 算法阶 | 二分 Θ(logn);归并/快排平均 Θ(nlogn);快排最坏 O(n²);Strassen \(n^{2.81}\);大整数乘 \(n^{1.59}\);最接近点对 Θ(nlogn);select Θ(n) |
| 机器提速 | 64 倍:2ⁿ→n+6,n²→8n;100 倍:n→100n,n²→10n,n³→4.64n,n!→n+6.64 |
10 · 自测(含历年真题)
- O(n) 的算法在相同规模下总比 O(2ⁿ) 的快。(Review 选择题变体)
- 时间复杂度只能描述最坏情况下算法的运行时间上界。
- 归并排序在基于比较的排序模型中渐近最优;计数排序等非比较排序在附加条件下可能突破此下界。
- 快速排序在任何输入下都是 O(n log n)。
💡 破题关键与第一步提示(遮答案自测用 · 答案)
破题切入点:✗——只保证 n 充分大后渐近意义(且“总是”太绝对,小规模常数因子可能反转)。(👉 先合上下方完整推导,自己动手算完关键步再核对踩分点!)
📝 完整规范推导与评分踩分点(答案)
- ✗——只保证 n 充分大后渐近意义(且“总是”太绝对,小规模常数因子可能反转)。
- ✗——时间复杂度可以讨论最坏、平均、最好或摊还情形;大 O 是渐近上界,并非“时间复杂度”一律等于最坏情况。
- ✓(仅限比较排序的最坏情况模型):比较排序下界 Ω(n log n),归并达到。
- ✗——最坏 O(n²)(已有序输入 + 固定划分元)。
- 解 \(X(n)=X(n/3)+1,\ X(1)=1,\ n=3^k\)。(答:\(1+\log_3 n\))
- 排序 \(4n^2,\ \log n,\ n!,\ 3^n,\ 20n,\ 2,\ n^{2/3}\)。(见 §3 例)
- 求最大最小元素的分治算法在 n=2ᵏ 时比较次数?(答:元素间比较 \(3n/2-2\) 次——分治两两比出胜负组再各比,优于朴素 2n−2;复习大纲点名的 Counting inversions 同属此类分治计数题。)
下一模块:动态规划与贪心——四步法、矩阵连乘/LCS/最大子段和/0-1背包/最优BST;贪心两要素、活动安排及正确性证明、贪心 vs DP 的分界(可拆背包 vs 0-1 背包)。
🎯 考场题型信号词 → 破题套路速查表 期末冲刺必背 · 信号词秒配定理与防扣分清单
考场上读题 10 秒内锁定“题干信号词”,直接调用中间列的定理模板作答,并在交卷前对照右列逐条排查高频扣分点。
| 🔍 题干信号词 / 设问特征 | ⚡ 必用定理 / 核心递推式 / 标准破题套路 | 🚨 老师批改高频扣分点 |
|---|---|---|
| 比较两个函数渐近阶 / 证明 \(f(n)=O(g(n)),\,\Omega(g(n)),\,\Theta(g(n))\) | 极限比值法 \(\lim_{n\to\infty} f(n)/g(n) = c\)(\(0| ⚠ 避坑:混淆上界 \(O\) 与紧确界 \(\Theta\);多项式 vs 指数 vs 对数阶排序出错(牢记 \((\log n)^k \ll n^\varepsilon \ll n^k \ll c^n \ll n!\)) |
|
| 机器提速 / 时间扩展为原来 \(k\) 倍求新最大可解规模 \(n'\) | 列出等式 \(T(n') = k\cdot T(n)\)(若机器速度变为 \(k\) 倍且运行相同时间),对多项式 \(n^d\) 得 \(n'=k^{1/d}n\)(乘法扩张),对指数 \(2^n\) 得 \(n'=n+\log_2 k\)(加法扩张) | ⚠ 避坑:把指数级 \(2^{n'}=k\cdot 2^n\) 错算成 \(n'=kn\)(审题看清“原规模为 \(n\)”还是“原耗时为 \(t\)”) |
| 求解分治递归方程 \(T(n)=aT(n/b)+f(n)\) | Master 定理三情形:比较 \(f(n)\) 与临界幂 \(n^{\log_b a}\) 是否存在多项式级差距 \(n^\varepsilon\);若仅差 \(\log^k n\) 因子(如 \(n^{\log_b a}\log^k n\)),用扩展情形 2 得 \(\Theta(n^{\log_b a}\log^{k+1} n)\) | ⚠ 避坑:遇到 \(T(n)=2T(n/2)+n\log n\) 误套情形 3(\(\log n\) 小于任意 \(n^\varepsilon\),多项式意义下不大于 \(n^1\),应得 \(\Theta(n\log^2 n)\)) |
| 设计分治算法(如芯片测试、大整数 Karatsuba、最接近点对、逆序对、第 \(k\) 小元素) | 严格按四步作答:① 子问题划分方式;② 递归求解与剪枝(減治还是分治);③ 合并策略(重点写清如何把合并耗时从 \(O(n^2)\) 降到 \(O(n)\));④ 列出 \(T(n)\) 并用主定理算阶 | ⚠ 避坑:在试卷上直接写 C/Python 代码块(2021 年历史复习资料强调文字分步说明与复杂度推导;今年是否允许直接写代码,以本学期任课教师通知为准) |
| 证明基于比较的排序或查找问题的时间下界 | 构造二叉决策树:\(n\) 个元素全排列共有 \(n!\) 个叶结点,树高 \(h\ge \lceil\log_2(n!)\rceil = \Omega(n\log n)\) | ⚠ 避坑:漏写“每次比较最多产生 2 个分支,深度为 \(h\) 的二叉树至多有 \(2^h\) 个叶子”这一关键桥梁不等式 |