分治法(Divide and Conquer)的核心思想就是"分而治之"。将一个复杂的大问题拆分为多个规模较小但结构相同的子问题,分别解决后再将结果合并,从而得到原问题的解。分治法是算法设计中最重要的策略之一,许多经典算法(如归并排序、快速排序)都基于分治思想。
分治法适用于那些可以自然地分解为重复子问题的问题,具体来说,一个问题适合用分治法解决需要满足以下条件:
分治法的解题思路通常遵循以下三个步骤:
以经典的汉诺塔问题为例,展示分治法的完整执行过程。
问题:将 3 个盘子从柱子 A 移动到柱子 C,可以借助柱子 B,规则是每次只能移动一个盘子,且大盘子不能放在小盘子上面。
分治思路:把"移动 n 个盘子从 A 到 C"拆分为三步:
1hanoi(3, A, B, C) — 把3个盘子从A移到C
2├── hanoi(2, A, C, B) — 先把上面2个从A移到B
3│ ├── hanoi(1, A, B, C) — 把1个从A移到C
4│ │ └── 移动:A → C (第1步)
5│ ├── 移动:A → B (第2步)
6│ └── hanoi(1, C, A, B) — 把1个从C移到B
7│ └── 移动:C → B (第3步)
8├── 移动:A → C (第4步)★ 移动最大盘
9└── hanoi(2, B, A, C) — 再把2个从B移到C
10 ├── hanoi(1, B, C, A) — 把1个从B移到A
11 │ └── 移动:B → A (第5步)
12 ├── 移动:B → C (第6步)
13 └── hanoi(1, A, B, C) — 把1个从A移到C
14 └── 移动:A → C (第7步)总共 7 步(2^3 - 1 = 7)。可以看到,n 个盘子需要 2^n - 1 步,每次递归都将问题规模减少 1。
遇到一个问题时,判断是否适合用分治法并设计解法:
