分治算法

Abstract

分治算法(Divide-and-Conquer Algorithm)是一种将规模为 的问题分解为若干规模更小的子问题、递归求解后合并结果的算法设计范式。其复杂度由分治递推关系 刻画,其中 为子问题个数, 为缩小因子, 为合并开销。经典应用包括归并排序 、二分查找 、快速整数乘法 和 Strassen 矩阵乘法

定义

分治算法(Divide-and-Conquer Algorithm)

分治算法遵循”分而治之”(Divide et impera)的策略,包含三个步骤:

  1. 分解(Divide):将规模为 的问题分解为 个规模为 的子问题
  2. 解决(Conquer):递归地求解每个子问题
  3. 合并(Combine):将子问题的解合并为原问题的解,合并开销为

表示求解规模为 的问题所需的总操作数,则

这称为分治递推关系

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

递推展开公式

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

由于 ,即 ,最终得到上述闭式。这是递归树法(recursion tree method)的代数基础,也是主定理证明的出发点。

核心性质

编号经典算法递推关系参数 复杂度说明
1二分查找每次缩减为规模 的子问题
2最大最小值查找两个子序列分别查找后合并比较
3归并排序合并两个有序子列表需 次比较
4快速整数乘法分解为 3 个 位乘法,
5Strassen 矩阵乘法7 个子矩阵乘法,
6最近点对带状区域每个点至多比较 7 个其他点
编号设计要素影响优化方向
A子问题个数 越少越好减少递归分支
B规模缩小因子 越大越好问题缩小得越快
C合并开销 越小越好高效的合并策略

关系网络

graph LR
    A["分治算法"] -->|"复杂度刻画"| B["[[离散数学/concepts/主定理]]"]
    A -->|"递推关系"| C["[[离散数学/concepts/递推关系]]"]
    A -->|"效率度量"| D["[[离散数学/concepts/算法复杂度]]"]
    A -->|"设计范式"| E["[[离散数学/concepts/算法]]"]
    A -->|"实现方式"| F["[[离散数学/concepts/递归算法]]"]
    A -->|"分析工具"| G["[[离散数学/concepts/大O记号]]"]

    A -->|"经典案例"| H["归并排序 O(n log n)"]
    A -->|"经典案例"| I["二分查找 O(log n)"]
    A -->|"经典案例"| J["快速整数乘法 O(n^1.585)"]
    A -->|"经典案例"| K["Strassen 矩阵乘法 O(n^2.807)"]
    A -->|"经典案例"| L["最近点对 O(n log n)"]

    B -->|"直接求解"| M["分治递推关系"]
    C -->|"建立"| M
    G -->|"表示复杂度"| D

章节扩展

第08章 高级计数技术 — 8.3 分治算法与递推关系

分治算法是 8.3 节的核心主题,本节系统介绍了分治递推关系的建立与求解方法:

  • 分治递推关系:一般形式 ,通过递推展开法可得闭式
  • Theorem 1 的特殊情况): 的解为 )或
  • 主定理 的三种情况判定,详见主定理
  • 最近点对问题:Michael Shamos 提出的分治算法,通过递归分割 + 带状区域检查实现 复杂度

递归树法分析

递归树法是理解分治算法复杂度的直观方法,将递推关系展开为一棵树:

  • 根节点:原问题,工作量为
  • 个子问题,每个规模为 ,每层总工作量
  • 叶子节点 个,每个工作量为
  • 总工作量:所有层的工作量之和

三种典型模式:

  • 每层工作量递减():根节点主导,
  • 每层工作量相同(): 层等量相加,
  • 每层工作量递增():叶子节点主导,

补充

分治思想的历史与直觉

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

分治算法的效率取决于三个因素:子问题个数 (越少越好)、规模缩小因子 (越大越好)、合并开销 (越小越好)。主定理精确地刻画了这三个因素如何共同决定最终复杂度。

Strassen 矩阵乘法的突破意义

Volker Strassen 于 1969 年发明的方法将两个 矩阵的乘法从传统的 降低到 。这一突破打破了”矩阵乘法不可能快于 “的长期直觉,开启了快速矩阵乘法的研究热潮。此后 Coppersmith-Winograd 等算法进一步将复杂度降至 以下。

参见