文章目录
要点3:能够推导一个递推关系的渐进阶(主方法)
📌 适合对象:算法学习者、计算机科学学生
⏱️ 预计阅读时间:50-60分钟
🎯 学习目标:掌握主方法(Master Method)求解递推关系,理解替换法和序列求和法,能够推导分治算法的时间复杂度
📚 参考PPT:第 1 章-PPT-N2_v4(算法概述)- 递推关系与主方法相关内容
📚 学习路线图
本文内容一览(快速理解)
- 递推关系基本形式: T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n),分治算法的标准形式
- 替换法:先猜想复杂度,然后用数学归纳法证明
- 序列求和法:逐步展开递推关系,对序列求和得到解
- 主方法:快速求解标准递推关系的三条规则
- 应用实例:分析归并排序、快速排序等算法的时间复杂度
一、递推关系的基本形式(Basic Recurrence Form):理解分治算法的时间复杂度
这一章要建立的基础:理解分治算法的复杂度通常可以表示为递推关系的形式。
核心问题:分治法的复杂度往往需要求解递推关系。如何表示这些递推关系?
[!NOTE]
📝 关键点总结:分治法的复杂度往往需要求解以下的递推关系: T ( 1 ) = c T(1) = c T(1)=c, T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n),其中 a a a是子问题个数, b b b是规模缩小的比例, f ( n ) f(n) f(n)是分解和合并的时间。
1.1 递推关系的含义(Meaning of Recurrence):理解各参数的意义
概念的本质:
分治法的复杂度通常可以表示为:
T ( 1 ) = c T(1) = c T(1)=c
T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n)
其中:
- a a a:分解成 a a a个子问题
- b b b:每个子问题规模是原问题的 1 / b 1/b 1/b
- f ( n ) f(n) f(n):分解和合并花费的总时间
图解说明:
💡 说明:求解递推关系的复杂度主要有两种方法:替换法(先猜想后证明)和序列求和法(逐步展开后求和)。主方法是用序列求和法时得到的一些结果的总结。
类比理解:
就像计算一个任务的总时间:
- 如果任务很小( n = 1 n=1 n=1),直接完成,时间是常数 c c c
- 如果任务较大(
n
n
n),需要:
- 花 f ( n ) f(n) f(n)时间分解任务
- 将任务分成 a a a个小任务,每个规模是原来的 1 / b 1/b 1/b
- 每个小任务需要 T ( n / b ) T(n/b) T(n/b)时间
- 花 f ( n ) f(n) f(n)时间合并结果
实际例子:
递推关系示例:
二元搜索的递推关系:
T(n) = T(n/2) + O(1)
含义:
- 分解:取中间元素,O(1)时间
- 子问题:1个子问题,规模n/2
- 合并:直接返回结果,O(1)时间
解:T(n) = O(log n)
归并排序的递推关系:
T(n) = 2T(n/2) + O(n)
含义:
- 分解:分成两半,O(1)时间
- 子问题:2个子问题,每个规模n/2
- 合并:合并两个有序序列,O(n)时间
解:T(n) = O(n log n)
二、替换法(Substitution Method):先猜想后证明
这一章要建立的基础:理解替换法是通过先猜想复杂度,然后用数学归纳法证明的方法。
核心问题:如何用替换法求解递推关系?
[!NOTE]
📝 关键点总结:替换法是求解递推关系的一种方法:1. 先猜想一个复杂度;2. 然后用数学归纳法证明其正确性。
2.1 替换法的步骤(Steps):猜想与证明
概念的本质:
替换法的步骤:
- 观察模式:通过观察小规模情况或使用其他方法(如递归树)来获得启发
- 猜想复杂度:根据观察猜测一个复杂度
- 证明上界:证明 T ( n ) = O ( . . . ) T(n) = O(...) T(n)=O(...)
- 证明下界:证明 T ( n ) = Ω ( . . . ) T(n) = \Omega(...) T(n)=Ω(...)
- 得到紧界:如果上界和下界相同,则 T ( n ) = Θ ( . . . ) T(n) = \Theta(...) T(n)=Θ(...)
图解说明:
💡 说明:替换法的关键是找到一个合适的猜测。通常可以通过观察小规模情况或使用其他方法(如递归树)来获得启发。
类比理解:
就像猜谜语:
- 先根据线索猜测答案
- 然后验证这个答案是否正确
- 如果正确,就找到了答案
实际例子:
替换法示例:
例:T(n) = 2T(⌊n/2⌋) + n,当n > 4时
T(n) = Θ(1),当1 ≤ n ≤ 4时
步骤1:观察模式
- T(8) = 2T(4) + 8
- T(4) = 2T(2) + 4
- 看起来像O(n log n)
步骤2:猜想
T(n) = Θ(n log n)
步骤3:证明上界T(n) = O(n log n)
- 归纳基础:当n = 4时,T(4) = Θ(1) ≤ c·4·log 4(取c > 1)
- 归纳步骤:假设T(k) ≤ c·k·log k对k < n成立
- 证明T(n) ≤ c·n·log n:
T(n) = 2T(⌊n/2⌋) + n
≤ 2c(⌊n/2⌋)log(⌊n/2⌋) + n
≤ 2c(n/2)log(n/2) + n
= cn(log n - 1) + n
= cn log n - cn + n
≤ cn log n(因为c > 1)
步骤4:证明下界T(n) = Ω(n log n)
(类似方法)
步骤5:因此T(n) = Θ(n log n)
三、序列求和法(Iteration Method):逐步展开后求和
这一章要建立的基础:理解序列求和法是从原递推关系逐步展开后得到一个序列,然后对该序列求和。
核心问题:如何用序列求和法求解递推关系?
[!NOTE]
📝 关键点总结:序列求和法是从原递推关系逐步展开后得到一个序列,然后对该序列求和后得到解。序列求和法中一步步展开的过程可以用一棵递归树来表示。
3.1 序列求和法的步骤(Steps):展开与求和
概念的本质:
序列求和法的步骤:
- 展开第1层:将 T ( n ) T(n) T(n)展开为 a T ( n / b ) + f ( n ) aT(n/b) + f(n) aT(n/b)+f(n)
- 展开第2层:继续展开 T ( n / b ) T(n/b) T(n/b)
- 继续展开:直到达到基础情况
- 得到序列:得到一个关于 f ( n ) f(n) f(n)的序列
- 对序列求和:求和后得到 T ( n ) T(n) T(n)的表达式
图解说明:
💡 说明:序列求和法中一步步展开的过程可以用一棵递归树来表示。递归树中每个节点对应着序列中的一项,所有节点的表达式的和等于T(n)。
类比理解:
就像展开一个嵌套的盒子:
- 打开第一层,看到里面的盒子和物品
- 继续打开里面的盒子
- 把所有物品加起来,就是总数
实际例子:
序列求和法示例:
例:T(n) = 2T(n/2) + n log n
展开过程:
T(n) = 2T(n/2) + n log n
= 2[2T(n/4) + (n/2)log(n/2)] + n log n
= 4T(n/4) + n log(n/2) + n log n
= 4[2T(n/8) + (n/4)log(n/4)] + n log(n/2) + n log n
= 8T(n/8) + n log(n/4) + n log(n/2) + n log n
= ...
= nT(1) + n[log n + log(n/2) + log(n/4) + ...]
= nT(1) + n[log n + (log n - 1) + (log n - 2) + ... + 1]
= nT(1) + n[log n(log n + 1)/2]
= Θ(n log² n)
递归树表示:
T(n)
/ \
T(n/2) T(n/2) [n log n]
/ \ / \
T(n/4) ... [n/2 log(n/2)]
...
四、主方法(Master Method):快速求解标准递推关系
这一章要建立的基础:理解主方法是快速求解标准递推关系的工具,有三条规则。
核心问题:如何用主方法快速求解递推关系?
[!NOTE]
📝 关键点总结:主方法是用序列求和法时得到的一些结果的总结。主方法主要有三条规则。检查递推关系满足哪条规则,如果满足,立马就有答案。设递推关系为 T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n), a ≥ 1 a \geq 1 a≥1, b > 1 b > 1 b>1。用规则前先计算 k k k值: k = log b a k = \log_b a k=logba。
4.1 主方法的三条规则(Three Rules):快速求解
概念的本质:
主方法的三条规则:
设递推关系为 T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n), a ≥ 1 a \geq 1 a≥1, b > 1 b > 1 b>1。
先计算 k = log b a k = \log_b a k=logba。
规则1:如果存在一个正数 ϵ > 0 \epsilon > 0 ϵ>0,使得 f ( n ) = O ( n k − ϵ ) f(n) = O(n^{k-\epsilon}) f(n)=O(nk−ϵ),那么 T ( n ) = Θ ( n k ) T(n) = \Theta(n^k) T(n)=Θ(nk)
规则2:如果 f ( n ) = Θ ( n k ) f(n) = \Theta(n^k) f(n)=Θ(nk),那么 T ( n ) = Θ ( n k log n ) T(n) = \Theta(n^k \log n) T(n)=Θ(nklogn)
规则3:如果存在一个正数 ϵ > 0 \epsilon > 0 ϵ>0,使得 f ( n ) = Ω ( n k + ϵ ) f(n) = \Omega(n^{k+\epsilon}) f(n)=Ω(nk+ϵ),并且存在一个正数 c < 1 c < 1 c<1,使得 a f ( n / b ) ≤ c f ( n ) af(n/b) \leq cf(n) af(n/b)≤cf(n),那么 T ( n ) = Θ ( f ( n ) ) T(n) = \Theta(f(n)) T(n)=Θ(f(n))
图解说明:
💡 说明:三种情况中的每一种,我们都是将f(n)与n^k相比较。两个函数大的决定递归式的解,并且,必须是多项式意义上的"大"。另外,第三种情况的成立,还需要满足正则条件af(n/b) ≤ cf(n),c<1。实际上,上述三种情况并未覆盖f(n)的所有情况,比如,情况1、2之间和情况2、3之间都存在一定间隙,使得主方法不适用。
类比理解:
就像判断两个数的大小关系:
- 如果 f ( n ) f(n) f(n)比 n k n^k nk小很多(规则1),复杂度由 n k n^k nk决定
- 如果 f ( n ) f(n) f(n)和 n k n^k nk差不多(规则2),复杂度是 n k log n n^k \log n nklogn
- 如果 f ( n ) f(n) f(n)比 n k n^k nk大很多(规则3),复杂度由 f ( n ) f(n) f(n)决定
实际例子:
主方法示例:
例1:T(n) = 9T(n/3) + n log n
解:
- a = 9, b = 3, k = log₃9 = 2
- f(n) = n log n
- 用ε = 0.2,那么 n^(k-ε) = n^(2-0.2) = n^1.8
- 因为 f(n) = n log n = O(n^1.8)(任何对数函数比多项式函数的阶要小)
- 满足规则1,所以T(n) = Θ(n²)
例2:T(n) = 2T(n/2) + n
解:
- a = 2, b = 2, k = log₂2 = 1
- f(n) = n = Θ(n¹) = Θ(n^k)
- 满足规则2,所以T(n) = Θ(n^k log n) = Θ(n log n)
例3:T(n) = 3T(n/2) + n²log n
解:
- a = 3, b = 2, k = log₂3 ≈ 1.58
- 用ε = 0.2,f(n) = n²log n = Ω(n^(1.58+0.2)) = Ω(n^1.78)
- 检查正则条件:
af(n/b) = 3(n/2)²log(n/2) = (3/4)n²log(n/2) ≤ (3/4)n²log n = cf(n)(c = 3/4 < 1)
- 满足规则3,所以T(n) = Θ(n²log n)
例4:T(n) = 2T(n/2) + n log n
解:
- a = 2, b = 2, k = log₂2 = 1
- f(n) = n log n
- 规则1:f(n) = n log n ≠ O(n^(1-ε))(无论ε多小)
- 规则2:f(n) = n log n ≠ Θ(n¹)
- 规则3:f(n) = n log n ≠ Ω(n^(1+ε))(无论ε多小)
- 主方法不适用,需要用序列求和法
五、应用实例(Applications):分析实际算法
这一章要建立的基础:通过实际算法例子,掌握如何应用主方法分析算法复杂度。
核心问题:如何用主方法分析实际算法的时间复杂度?
[!NOTE]
📝 关键点总结:主方法可以快速分析许多分治算法的时间复杂度,包括归并排序、快速排序等。
5.1 归并排序的复杂度分析(Merge Sort Analysis)
概念的本质:
归并排序的递推关系: T ( n ) = 2 T ( n / 2 ) + O ( n ) T(n) = 2T(n/2) + O(n) T(n)=2T(n/2)+O(n)
使用主方法:
- a = 2 a = 2 a=2, b = 2 b = 2 b=2, k = log 2 2 = 1 k = \log_2 2 = 1 k=log22=1
- f ( n ) = n = Θ ( n 1 ) = Θ ( n k ) f(n) = n = \Theta(n^1) = \Theta(n^k) f(n)=n=Θ(n1)=Θ(nk)
- 满足规则2,所以 T ( n ) = Θ ( n k log n ) = Θ ( n log n ) T(n) = \Theta(n^k \log n) = \Theta(n \log n) T(n)=Θ(nklogn)=Θ(nlogn)
实际例子:
归并排序复杂度分析:
算法:Mergesort(A[p..r])
- 分:将数组分为两半
- 递归:分别排序两半
- 合:合并两个有序序列,需要O(n)时间
递推关系:T(n) = 2T(n/2) + O(n)
主方法求解:
- a = 2, b = 2, k = log₂2 = 1
- f(n) = n = Θ(n¹) = Θ(n^k)
- 满足规则2
- 所以T(n) = Θ(n log n)
结论:归并排序的时间复杂度为Θ(n log n)
5.2 快速排序的复杂度分析(Quick Sort Analysis)
概念的本质:
快速排序的平均情况递推关系: T ( n ) = T ( n / 2 ) + T ( n / 2 ) + O ( n ) = 2 T ( n / 2 ) + O ( n ) T(n) = T(n/2) + T(n/2) + O(n) = 2T(n/2) + O(n) T(n)=T(n/2)+T(n/2)+O(n)=2T(n/2)+O(n)(平均情况下划分是平衡的)
使用主方法:
- a = 2 a = 2 a=2, b = 2 b = 2 b=2, k = log 2 2 = 1 k = \log_2 2 = 1 k=log22=1
- f ( n ) = n = Θ ( n 1 ) = Θ ( n k ) f(n) = n = \Theta(n^1) = \Theta(n^k) f(n)=n=Θ(n1)=Θ(nk)
- 满足规则2,所以 T ( n ) = Θ ( n log n ) T(n) = \Theta(n \log n) T(n)=Θ(nlogn)
实际例子:
快速排序复杂度分析:
平均情况:
- 划分:O(n)时间
- 递归:平均情况下,左右两部分各n/2
- 递推关系:T(n) = 2T(n/2) + O(n)
- 主方法:T(n) = Θ(n log n)
最坏情况(已有序):
- 划分:每次只减少1个元素
- 递推关系:T(n) = T(n-1) + O(n)
- 解:T(n) = O(n²)
📝 本章总结
核心要点回顾:
-
递推关系基本形式: T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n)
- a a a:子问题个数
- b b b:规模缩小比例
- f ( n ) f(n) f(n):分解和合并时间
-
替换法:先猜想后证明
- 观察模式,猜想复杂度
- 用数学归纳法证明上界和下界
-
序列求和法:逐步展开后求和
- 展开递推关系
- 对序列求和得到解
-
主方法:快速求解标准递推关系
- 规则1: f ( n ) = O ( n k − ϵ ) f(n) = O(n^{k-\epsilon}) f(n)=O(nk−ϵ) → T ( n ) = Θ ( n k ) T(n) = \Theta(n^k) T(n)=Θ(nk)
- 规则2: f ( n ) = Θ ( n k ) f(n) = \Theta(n^k) f(n)=Θ(nk) → T ( n ) = Θ ( n k log n ) T(n) = \Theta(n^k \log n) T(n)=Θ(nklogn)
- 规则3: f ( n ) = Ω ( n k + ϵ ) f(n) = \Omega(n^{k+\epsilon}) f(n)=Ω(nk+ϵ)且满足正则条件 → T ( n ) = Θ ( f ( n ) ) T(n) = \Theta(f(n)) T(n)=Θ(f(n))
-
应用:分析归并排序、快速排序等分治算法
知识地图:
关键决策点:
- 何时使用替换法:递推关系不标准,或需要精确分析
- 何时使用序列求和法:主方法不适用,需要详细展开
- 何时使用主方法:递推关系是标准形式 T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n)
- 如何选择规则:比较 f ( n ) f(n) f(n)与 n k n^k nk的大小关系
💡 延伸学习:主方法是分析分治算法复杂度的强大工具。掌握主方法可以快速分析许多经典算法,包括:
- 归并排序: T ( n ) = 2 T ( n / 2 ) + O ( n ) T(n) = 2T(n/2) + O(n) T(n)=2T(n/2)+O(n) → Θ ( n log n ) \Theta(n \log n) Θ(nlogn)
- 快速排序(平均): T ( n ) = 2 T ( n / 2 ) + O ( n ) T(n) = 2T(n/2) + O(n) T(n)=2T(n/2)+O(n) → Θ ( n log n ) \Theta(n \log n) Θ(nlogn)
- 二元搜索: T ( n ) = T ( n / 2 ) + O ( 1 ) T(n) = T(n/2) + O(1) T(n)=T(n/2)+O(1) → Θ ( log n ) \Theta(\log n) Θ(logn)
- 堆排序: T ( n ) = 2 T ( n / 2 ) + O ( log n ) T(n) = 2T(n/2) + O(\log n) T(n)=2T(n/2)+O(logn) → Θ ( n ) \Theta(n) Θ(n)(建堆)
1万+

被折叠的 条评论
为什么被折叠?



