【计算机算法与设计(3)】推导一个递推关系的渐进阶(主方法)

AgenticCoding·十二月创作之星挑战赛 10w+人浏览 282人参与

要点3:能够推导一个递推关系的渐进阶(主方法)

📌 适合对象:算法学习者、计算机科学学生
⏱️ 预计阅读时间:50-60分钟
🎯 学习目标:掌握主方法(Master Method)求解递推关系,理解替换法和序列求和法,能够推导分治算法的时间复杂度
📚 参考PPT:第 1 章-PPT-N2_v4(算法概述)- 递推关系与主方法相关内容


📚 学习路线图

递推关系求解
替换法
Substitution Method
序列求和法
Iteration Method
主方法
Master Method(重点)
先猜想后证明
逐步展开后求和
三条规则快速求解
应用:分析算法复杂度

本文内容一览(快速理解)

  1. 递推关系基本形式 T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n),分治算法的标准形式
  2. 替换法:先猜想复杂度,然后用数学归纳法证明
  3. 序列求和法:逐步展开递推关系,对序列求和得到解
  4. 主方法:快速求解标准递推关系的三条规则
  5. 应用实例:分析归并排序、快速排序等算法的时间复杂度

一、递推关系的基本形式(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):分解和合并花费的总时间

图解说明

T(n)
分解:f(n)时间
a个子问题
每个规模n/b
T(n/b)
T(n/b)
T(n/b)
合并:f(n)时间
总时间:aT(n/b) + 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):猜想与证明

概念的本质

替换法的步骤:

  1. 观察模式:通过观察小规模情况或使用其他方法(如递归树)来获得启发
  2. 猜想复杂度:根据观察猜测一个复杂度
  3. 证明上界:证明 T ( n ) = O ( . . . ) T(n) = O(...) T(n)=O(...)
  4. 证明下界:证明 T ( n ) = Ω ( . . . ) T(n) = \Omega(...) T(n)=Ω(...)
  5. 得到紧界:如果上界和下界相同,则 T ( n ) = Θ ( . . . ) T(n) = \Theta(...) T(n)=Θ(...)

图解说明

递推关系T(n)
观察模式
猜想复杂度
证明上界
T(n) = O(...)
证明下界
T(n) = Ω(...)
得到紧界
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. 展开第1层:将 T ( n ) T(n) T(n)展开为 a T ( n / b ) + f ( n ) aT(n/b) + f(n) aT(n/b)+f(n)
  2. 展开第2层:继续展开 T ( n / b ) T(n/b) T(n/b)
  3. 继续展开:直到达到基础情况
  4. 得到序列:得到一个关于 f ( n ) f(n) f(n)的序列
  5. 对序列求和:求和后得到 T ( n ) T(n) T(n)的表达式

图解说明

T(n) = aT(n/b) + f(n)
展开第1层
T(n) = a[aT(n/b²) + f(n/b)] + f(n)
展开第2层
继续展开...
得到序列
对序列求和
得到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 a1 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 a1 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
f(n) = n^k
f(n) >> n^k
满足
不满足
递推关系T(n) = aT(n/b) + f(n)
计算k = log_b a
比较f(n)与n^k
规则1
T(n) = Θ(n^k)
规则2
T(n) = Θ(n^k log n)
检查正则条件
af(n/b) ≤ cf(n)
规则3
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²)

 


📝 本章总结

核心要点回顾

  1. 递推关系基本形式 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):分解和合并时间
  2. 替换法:先猜想后证明

    • 观察模式,猜想复杂度
    • 用数学归纳法证明上界和下界
  3. 序列求和法:逐步展开后求和

    • 展开递推关系
    • 对序列求和得到解
  4. 主方法:快速求解标准递推关系

    • 规则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))
  5. 应用:分析归并排序、快速排序等分治算法

知识地图

递推关系求解
替换法
猜想+证明
序列求和法
展开+求和
主方法
三条规则
规则1:f(n) << n^k
规则2:f(n) = n^k
规则3:f(n) >> n^k
应用:算法分析

关键决策点

  • 何时使用替换法:递推关系不标准,或需要精确分析
  • 何时使用序列求和法:主方法不适用,需要详细展开
  • 何时使用主方法:递推关系是标准形式 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的大小关系

💡 延伸学习:主方法是分析分治算法复杂度的强大工具。掌握主方法可以快速分析许多经典算法,包括:

  1. 归并排序: 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)
  2. 快速排序(平均): 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)
  3. 二元搜索: 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)
  4. 堆排序: 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)(建堆)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

roman_日积跬步-终至千里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值