Skip to content

Commit 0517935

Browse files
committed
增加减治法、分治法和变治法的说明
1 parent ad1d866 commit 0517935

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
11
[#0000-21-decrease-and-conquer]
22
= Decrease and Conquer 减治法
33

4+
D瓜哥最早知道减治法是在 https://book.douban.com/subject/26337727/[《算法设计与分析基础》^] 中。这里也直接引用该书的介绍。
5+
6+
减治(decrease-and-conquer)技术利用了一个问题给定实例的解和同样问题较小实例的解之间的某种关系。自底向上版本往往是迭代实现的,从求解问题的一个较小实例开始,该方法有时也称为增量法(Incremental Approach)。
7+
8+
减治法有3种主要的变化形式:
9+
10+
* **减去一个常量。**在减常量(decrease-by-a-constant)变化形式中,每次算法迭代总是从实例中减去一个相同的常量。
11+
** 插入排序
12+
* **减去一个常量因子。**减常因子(decrease-by-a-constant-factor)技术意味着在算法的每次迭代中,总是从实例的规模中减去一个相同的常数因子。在大多数应用中,这样的常数因子等于2,其实就是减半。
13+
** 二分查找
14+
* **减去的规模是可变的。**在减治法的减可变规模(variable-size-decrease)变化形式中,算法在每次迭代时,规模减小的模式都是不同的。
15+
** 计算最大公约数的欧几里得算法是这种情况的一个很好的例子。 stem:[gcd(m, n)=gcd(n,m mod n)]
16+

docs/0000-22-divide-and-conquer.adoc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,54 @@
11
[#0000-22-divide-and-conquer]
22
= Divide and Conquer 分治法
33

4+
关于分治法的内容,这里继续参考 https://book.douban.com/subject/26337727/[《算法设计与分析基础》^] 中的内容。
5+
6+
分治法是按照以下方案工作的。
7+
8+
. 将一个问题划分为同一类型的若干子问题,子问题最好规模相同。
9+
. 对这些子问题求解(一般使用递归方法,但在问题规模足够小时,有时也会利用另一个算法)。
10+
. 有必要的话,合并这些子问题的解,以得到原始问题的答案。
11+
12+
image::/images/data-structure/divide-and-conquer-1.png[title="分治法",alt="分治法",{image_attr}]
13+
14+
从字面上分析就可以看到有哪些步骤:
15+
16+
* 分-分解-将问题分解为规模更小的子问题,子问题最好相同或相似;
17+
* 治-求解-将这些规模更小的子问题逐个击破;
18+
* 合-合并-将已解决的子问题合并,最终得出原问题的解;
19+
20+
从上述步骤中我们可以看出,分治算法一般适用满足以下条件的场景:
21+
22+
. 问题规模缩小到一定的程度就可以很容易解决;
23+
. 问题**可以分解**为若干个规模较小的相同问题;
24+
. 问题分解出的若干子问题的解可以合并为该问题的解;
25+
. 每个子问题都是**独立**的,相互之间没有交集。(这是区别分治法与减)
26+
27+
在“分”的过程中,我们尽可能让分解出的子问题与原始问题相似,而规模更小。这刚好符合递归的特性。因此,分治法往往与递归联系在一起。
28+
29+
在分治法最典型的运用中,问题规模为 `n` 的实例被划分为两个规模为 `n/2` 的实例。更一般的情况下,一个规模为 `n` 的实例可以划分为 `b` 个规模为 `n/b` 的实例,其中 `a` 个实例需要求解(这里,`a``b` 是常量,`a≥1``b>1`)。
30+
31+
[.text-center]
32+
[stem]
33+
++++
34+
T(n) = aT(n/b) + f(n)
35+
++++
36+
37+
其中,stem:[f(n)] 是一个函数,表示将问题分解为小问题和将结果合并起来所消耗的时间
38+
39+
分治法的典型案例如下:
40+
41+
. 归并排序
42+
. 快速排序
43+
. 二叉树的经典遍历算法和其他类似的算法都需要递归处理左右两棵子树
44+
. Strassen 算法
45+
. 最近对问题
46+
. 凸包问题
47+
48+
分治法对**分治出的部分需要分别处理**,进行分开的单独计算,而减治法则利用了"一个问题给定实例的解和同样问题较小实例的解之间的关系",只针对部分子问题求解,*减治掉的那部分就不需要了*
49+
50+
减常因子的减治法也可以看做是分治的变种。
51+
452
== 经典题目
553

654
. xref:0004-median-of-two-sorted-arrays.adoc[4. Median of Two Sorted Arrays]
Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,30 @@
11
[#0000-23-transform-and-conquer]
2-
= Transform and Conquer 变知法
2+
= Transform and Conquer 变治法
3+
4+
D瓜哥最早知道变治法也是在 https://book.douban.com/subject/26337727/[《算法设计与分析基础》^] 中。这里也直接引用该书的介绍。
5+
6+
变治法,就是基于变换的一种思想方法,首先把问题的实例变得容易求解,然后进行求解。
7+
8+
变治法的工作可以分成两个阶段:首先把问题变得更容易求解,然后对实例进行求解。根据我们对问题实例的变换方式,变治思想有3种主要的类型:
9+
10+
. 实例化简(Instance simplification) -- 指将原问题变换为同样问题的一个更简单或者更方便的实例。一个典型的案例是:去重时,先排序,
11+
.. 列表预排序
12+
... 检验数组中元素的唯一性
13+
... 模式计算
14+
... 查找问题
15+
.. 高斯消元法
16+
... 系数矩阵的LU分解(LU decomposition)
17+
... 计算矩阵的逆
18+
... 计算矩阵的行列式
19+
.. AVL 树
20+
. 改变表现(Representation Change) -- 指将原问题变换为同样实例的不同表现。经典的栗子:霍纳法则。
21+
.. 多路平衡查找树(最简单的情况:2-3树)
22+
.. 求多项式的霍纳法则
23+
.. 两种二进制幂算法
24+
.. 堆排序
25+
. 问题化简(Problem reduction) -- 指把一个给定的问题变换为另一个可以用已知算法求解的问题。(归化思想)转换的难题在于如何找到一个变换的目标算法。典型案例是背包问题,背包问题的本质是线性规划。了解了线性规划的本质后,才能更好地解决高维的背包问题。
26+
.. 求最小公倍数
27+
.. 计算图中的路径数量
28+
.. 最优化问题(最大化问题(maximization problem)、最小化问题(minimization problem))
29+
.. 线性规划(单纯形法、0/1背包问题)
30+
.. 简化为图问题

0 commit comments

Comments
 (0)