相关笔记: 8.2 求解线性递推关系 | 8.4 生成函数

概览

本节系统介绍了分治算法(divide-and-conquer algorithms)的复杂度分析方法。分治算法将规模为 的问题分解为若干规模更小的子问题,递归求解后合并结果。其复杂度可用分治递推关系 描述。

  • 分治递推关系的一般形式:,其中 为子问题个数, 为缩小因子, 为合并开销
  • 主定理(Master Theorem)提供了分治递推关系复杂度的直接判定方法,分为三种情况
  • 经典应用:归并排序 、二分查找 、快速整数乘法 、Strassen 矩阵乘法
  • 最近点对问题可通过分治算法在 时间内求解

一、知识结构总览

graph TB
    A["8.3 分治算法与递推关系<br/>Divide-and-Conquer Algorithms"] --> B["分治递推关系"]
    A --> C["主定理 Master Theorem"]
    A --> D["经典分治算法"]
    A --> E["最近点对问题"]

    B --> B1["一般形式 f(n) = af(n/b) + g(n)"]
    B --> B2["参数含义:a, b, g(n)"]
    B --> B3["递推展开法"]

    C --> C1["情况1:a < b^d → O(n^d)"]
    C --> C2["情况2:a = b^d → O(n^d log n)"]
    C --> C3["情况3:a > b^d → O(n^{log_b a})"]
    C --> C4["Theorem 1:g(n) = c 的特殊情况"]

    D --> D1["二分查找 O(log n)"]
    D --> D2["归并排序 O(n log n)"]
    D --> D3["快速整数乘法 O(n^{log 3})"]
    D --> D4["Strassen 矩阵乘法 O(n^{log 7})"]
    D --> D5["最大最小值查找 O(n)"]

    E --> E1["递归分割 + 带状区域检查"]
    E --> E2["O(n log n) 复杂度"]

二、核心思想

核心思想

本节的核心思想是分治递推关系的建立与求解。分治算法遵循”分而治之”(Divide et impera)的策略:将规模为 的问题分解为 个规模为 的子问题,分别求解后用 的额外开销合并结果。由此产生的递推关系 可以通过递推展开法或主定理直接求解复杂度,而无需逐项展开。

1. 分治递推关系

分治递推关系(Divide-and-Conquer Recurrence Relation)

设一个递归算法将规模为 的问题分解为 个规模为 的子问题(假设 的倍数),且合并子问题的解需要 次额外操作。若 表示求解规模为 的问题所需的总操作数,则

这称为分治递推关系

  • :子问题的个数
  • :问题规模缩小的因子( 的整数)
  • :合并步骤的额外开销
  • 不是 的幂时,子问题规模取

二分查找(Binary Search)

二分查找将规模为 的搜索问题缩减为规模为 的子问题(),每次缩减需要 2 次比较(一次确定搜索哪一半,一次检查是否还有剩余元素)。

由 Theorem 1(),

查找最大值和最小值(Example 2)

将含 个元素的序列分成两个含 个元素的子序列(),分别找最大最小值后,需要 2 次比较(比较两个最大值、比较两个最小值)。

由 Theorem 1(),

归并排序(Merge Sort)

归并排序将含 个元素的列表分成两个含 个元素的子列表(),排序后合并需要不超过 次比较。

由主定理(),,故

快速整数乘法(Example 4)

将两个 位整数的乘法分解为三个 位整数的乘法,加上移位和加法操作。设 为两个 位整数相乘所需的位运算次数:

其中 代表加法、减法和移位的总位运算数。由主定理(),,故 。由于 ,这比传统乘法算法的 有显著改进。

Strassen 矩阵乘法(Example 5)

Volker Strassen 于 1969 年发明的方法将两个 矩阵的乘法( 为偶数时)分解为 7 个 矩阵的乘法和 15 个 矩阵的加法。

由主定理(),,故 。由于 ,这比传统矩阵乘法的 更高效。

2. 递推展开法

递推展开公式

,且 为正整数)。反复展开递推关系:

由于 ,即 ,最终得到:

3. Theorem 1: 的特殊情况

Theorem 1( 时分治递推的解)

是递增函数,满足递推关系

其中 的倍数, 是大于 的整数, 为正常数。则

进一步,当 时,,其中

证明:取 ,代入递推展开公式:

因为 ,故 。当 不是 的幂时,,由 递增:

:利用等比数列求和公式: 因为 (见附录 2 练习 4),其中

不是 的幂时,,由 递增:

求解

由 Theorem 1 的证明,取 。当 时:

递增,则

4. 主定理(Master Theorem)

Theorem 2 — 主定理(Master Theorem)

是递增函数,满足递推关系

其中 为正整数), 是大于 的整数,。则

证明思路(Exercises 29-33):

情况1):利用 Exercise 29-30,可证 。直观理解:每层递归的总合并开销为 ,由于 ,这是一个递减的等比数列,总开销以首项 为上界。

情况2):利用 Exercise 31-32,可证 。直观理解:每层递归的总合并开销为 (常数),共有 层,故总开销为

情况3):利用 Exercise 31 和 33,可证 。直观理解:底层(叶子节点)有 个,每个叶子开销为 ,底层总开销主导。

主定理使用注意事项

  • 主定理要求 递增函数,且 的形式
  • 时,复杂度多了一个 因子,这是最容易出错的地方
  • 判断的关键是比较 的大小关系,而非 的大小关系
  • 例如归并排序:,故

5. 最近点对问题

最近点对问题(Closest-Pair Problem)

给定平面上 个点 ,求距离最近的点对。两点间的距离使用欧几里得距离

分治算法(Michael Shamos):

  1. 预处理:用归并排序按 坐标和 坐标分别排序,
  2. 递归分割:用垂直线 将点集分成左右两半各 个点
  3. 递归求解:分别求左半和右半的最近距离 ,令
  4. 合并检查:只需检查宽度为 的带状区域内的点对
  5. 关键观察:对带状区域内的每个点 ,只需检查以 为中心的 矩形内的点,该矩形中至多 8 个点(因为每个 的小正方形中至多 1 个点,对角线长

递推关系:(带状区域内每个点至多比较 7 个其他点)

由主定理(),,故

加上预处理的 ,总复杂度为 ,远优于暴力法的


三、补充理解与易混淆点

补充理解

补充1:分治思想的历史与直觉

“分而治之”(Divide et impera)的思想可追溯到古罗马的凯撒大帝。在计算机科学中,分治策略是最高效的算法设计范式之一。其核心直觉可以用”组织大型活动”来类比:如果要组织 1000 人的活动,直接管理所有人效率极低( 的沟通成本);更好的方式是将 1000 人分成若干小组,每组指定组长,再由组长管理组员——这就是分治思想的本质。

分治算法的效率取决于三个因素:

  • 子问题的个数 :越少越好
  • 规模缩小因子 :越大越好(问题缩小得越快)
  • 合并开销 :越小越好

主定理精确地刻画了这三个因素如何共同决定最终复杂度。 来源:Cormen, T. H., et al. (2009). Introduction to Algorithms (3rd ed.), MIT Press, Chapter 4. 来源:Aho, A. V., Hopcroft, J. E. & Ullman, J. D. (1974). The Design and Analysis of Computer Algorithms. Addison-Wesley, Chapter 2.

补充2:主定理三种情况的直觉理解

可以用”树形递归”的视角理解主定理的三种情况。将分治递推展开为一棵递归树:

  • 情况1):每层的工作量按 递减,总工作量以根节点的工作量 为上界——合并开销主导
  • 情况2):每层的工作量相同,都是 ,共 层——总工作量
  • 情况3):工作量随层数递增,总工作量以叶子节点的工作量 为上界——递归开销主导

这种递归树分析法(recursion tree method)是理解主定理的最佳方式,也是《算法导论》(CLRS)第4章推荐的分析方法。 来源:Cormen, T. H., et al. (2009). Introduction to Algorithms (3rd ed.), MIT Press, Chapter 4, Theorem 4.1. 来源:Akra, M. & Bazzi, L. (1998). “On the Solution of Linear Recurrences.” Computational Complexity, 7(1), 3–21.

易混淆点

误区: 的比较 vs 的比较

  • ❌ 比较的是 的大小来判断复杂度
  • ✅ 主定理比较的是 的大小,其中 中的指数
  • 例如: 中,,故
  • 但若 ,则 ,故

误区: 时忘记 因子

  • ❌ 认为 的复杂度是
  • ,属于情况2,正确答案是
  • 直觉:每层合并开销都是 ,共 层,总开销

误区:混淆 Theorem 1 和主定理(Theorem 2)

  • Theorem 1 是主定理在 (即 )时的特殊情况
  • 时,,所以:
    • (即 ),情况3:
    • (即 ),情况2:(因为
  • Theorem 1 的结论与主定理完全一致

四、习题精选

习题概览

题号范围核心考点难度
1-2二分查找/最大最小值的比较次数计算
3-5快速整数乘法的手动执行与复杂度估计⭐⭐
6Strassen 矩阵乘法的操作数计算⭐⭐
7-9递推关系的逐层展开与精确求解⭐⭐
10-13递推关系的精确求解与 big-O 估计⭐⭐⭐
14-16淘汰赛递推关系⭐⭐
17-18多数票问题的分治算法设计⭐⭐⭐
19-20快速幂算法的递推关系⭐⭐⭐
21-22非标准分治递推( 分割)⭐⭐⭐⭐
23最大连续子序列和的分治算法⭐⭐⭐⭐
24-25最近点对问题的手动执行⭐⭐⭐
26-27最近点对算法的伪代码与变体⭐⭐⭐
28-33Ulam 搜索问题(含一次撒谎)⭐⭐⭐⭐
34-37非标准 值的递推关系求解⭐⭐⭐

题1:二分查找的比较次数

题目

在 64 个元素的有序集合中进行二分查找需要多少次比较?

题2:最大最小值的比较次数

题目

使用 Example 2 的算法在含 128 个元素的序列中查找最大值和最小值,需要多少次比较?

题3:求解分治递推关系

题目

是 3 的倍数),。求

题4:利用主定理估计复杂度

题目

。若 递增,给出 的 big-O 估计。

题5:Strassen 矩阵乘法的操作数

题目

使用 Example 5 中的 Strassen 算法,计算两个 矩阵的乘法需要多少次乘法和加法?

解题思路提示

分治递推关系的解题方法论:

  1. 识别参数:从递推关系中确定 (子问题个数)、(缩小因子)、 的形式
  2. 套用主定理:将 写成 的形式,比较
  3. 特殊情况:当 (常数)时,直接使用 Theorem 1
  4. 精确求解:当 的幂时,可利用递推展开公式求精确解
  5. 非标准情况:当递推关系不符合主定理形式时(如 ),需使用递归树法或其他方法

五、视频学习指南

视频资源

资源链接对应内容备注
Rosen 8e Section 8.3教材原文完整定义、定理与例题英文教材
MIT 6.006 Lecture 2链接分治算法与主定理英文,MIT开放课程
CLRS Chapter 4链接递归树法与主定理证明英文

六、教材原文

教材原文

“Many recursive algorithms take a problem with a given input and divide it into one or more smaller problems. This reduction is successively applied until the solutions of the smaller problems can be found quickly.”

“This theorem (or more powerful versions, including big-Theta estimates) is sometimes known as the master theorem because it is useful in analyzing the complexity of many important divide-and-conquer algorithms.”

“It took researchers more than 10 years to find an algorithm with complexity that locates the closest pair of points among points.”


参见 Wiki

高级计数技术