第5章 分治法

分治法

将规模为N的问题分解为k个规模较小的子问题,使这些子问题相互独立可分别求解,再将k个子问题的解合并成原问题的解.如子问题的规模仍很大,则反复分解直到问题小到可直接求解为止。
在分治法中,子问题的解法通常与原问题相同,自然导致递归过程。

特点:
算法适宜并行计算
算法的计算复杂度对应如此递归方程 T(n)=aT(n/b)+f(n)

  • T(n)=aT(n/b)+f(n)递推式的解法

合并排序

  • 算法思想:若n为1,算法终止;
    否则,将n个待排元素分割成k(k=2)个大致相等子集合A、B,对每一个子集合分别递归排序,
    再将排好序的子集归并为一个集合。

  • 合并:
    前提:数组B及数组C已经有序。
    比较数组B的第一个记录与数组C的第一个记录将KEY值小者输出至数组A,再从相应数组读进一个记录,替代已被输出的记录,再继续比较。
    结束:直至有一个数组的记录已被穷尽,然后再将未穷尽的数组上的所有记录拷贝到输出数组A上。
    C(n) = 2C(n/2)+Cmerge(n)
    最坏情况:
    归并过程的最坏复杂度为 Cmerge(n)=n-1,
    排序算法的最坏复杂度为
    C (n)=2C(n/2)+n-1
    解得C(n)=nlog2n-n+1∈Θ(nlog2n)

  • 合并排序总结:
    最坏情况Θ(nlog2n)
    优点:
    1.合并排序在最坏情况下的键值比较次数十分接近于任何基于比较的排序算法在理论上能够达到的最少次数
    2.合并排序精确解Cworst(n)=nlog2n-n+1
    3.理论最小值nlog2n-1.44n向上取整
    缺点:
    1.需要线性的额外空间
    2.虽然合并也可做到“在位”,但导致算法过于复杂

给予合并排序思想找出n个元素中第k个最小元素:
将n个元素分为每段有k个元素的有序段,两个k元素有序段合并成一个k元素有序段,递归此过程。

快速排序

  • 算法思路:
    对于输入A[0.. n-1],按以下三个步骤进行排序:
    1.分区:取A中的一个元素为支点(pivot) 将A[0..n-1]划分成3段: A[0..s-1], A[s ], A[s+1..n-1], 使得
    A[0..s-1]中任一元素<=A[s],
    A[s+1..n-1]中任一元素>=A[s]; 下标s 在划分过程中确定。
    2.递归求解:递归调用快速排序法分别对A[0..s-1]和A[s+1..n-1]排序。
    3.合并:合并A[0..s-1], A[s], A[s+1..n-1]为A[0..n-1]
  • 整个算法的最坏情况下:
    在进行了n+1次比较后建立了分区,还会对数组进行排序, 继续到最后一个子数组A[n-2..n-1]。总比较次数为:
    Cworst(n)=(n+1)+n+…+3
    =(n+2)(n+1)/2-3
    ∈Θ(n2)
  • 最好情况
    每次分区执行n次
    并且每次都是等分
    Cbest(n)=2Cbest(n/2)+n
    ∈Θ(nlog2n)
  • 平均情况
    分裂点有可能在一次分区后出现在每个位置
    设概率是1/n


    图片1.png

基于快排思想找第k个最小元素
算法思想:
1.任选一个元素为支点a
2.将集合中的元素划分成S1与S2,其中S1={x|x<a} S2={x|x>a}
3.依据S1与S2大小确定第k个最小元素所在的集合,不妨设为S1
4.在S1上递归应用以上思想直到第k个最小元素被找出
复杂度:
最坏情况下 T(n)=T(n-1)+O(n)
并且当k约等于n/2时,T(n)为O(n2)
平均情况下 每次递归均在n/2的子表上进行,即复杂度满足 T(n)=T(n/2)+O(n) 即T(n)=O(n)。

二叉树的遍历及其相关特性

所谓二叉树的遍历指的是遵循某一种次序来访问二叉树上的所有结点,使得树中每一个结点被访问了一次且只访问一次。
由于二叉树是一种非线性结构,树中的结点可能有不止一个的直接后继结点,所以遍历以前必须先规定访问的次序。

  • 中序遍历
    二叉树的中序遍历算法比较简单,使用递归的策略。在遍历以前首先确定遍历的树是否为空,如果为空,则直接返回;否则中序遍历的算法步骤如下:
    (1)对左子树L执行中序遍历算法
    (2)访问输出根结点V的值。
    (3)对右子树R执行中序遍历算法。
  • 先序遍历
    有了上面的中序遍历的过程,前序遍历也是类似的。在遍历以前首先确定遍历的树是否为空,如果为空,则直接返回;否则前序遍历的算法步骤如下:
    (1)访问输出根结点V的值;
    (2)对左子树L执行前序遍历算法。
    (3)对右子树R执行前序遍历算法。

大整数乘法

分治法如何体现。
令N为偶数,则A和B可表示为
其中a1和a2分别为A的前半部和后半部。
A=a1·10N/2+a2 (123456=123·106/2+456)
B=b1·10N/2+b2
b1和b2则分别为B的前半部和后半部。如果按下述方法得到积(多项式相乘)
A·B=(a110n/2+a2)(b110n/2+b2)
=a1b110n+(a1b2+a2b1)10n/2+a2b2

要4次N/2位乘法,即N2次一位乘法。因此这种方法没有改进原来的方法。
T(n) = 4 T(n/2) + O(n) ------------ O(n2)

改进:
(a1+a2)(b1+b2) = a1b1 + a1b2 + a2b1 + a2b2
若认定 a1b1 与 a2b2 为必须计算的,则
a1b2 + a2b1 = (a1+a2)(b1+b2) - a1b1- a2b2
左边的两次乘法, 转换成 右边的 3 次乘法!

这种方法需要3次n/2位的乘法及一些加减法。
记C(n)为计算两个n位整数相乘所需的基本操作(1位数的乘法或加法)执行次数,则
有 C(n)=3C(n/2)+k·n
C(1)=1
其中,k为常数, k·n表示加法、减法所需时间与n成正比。 解此递归方程 得
C(n)=nlog3+2knlog3-2kn
所以 C(n)∈O(nlog3) ≈ O(n1.58)

Strassen矩阵乘法

普通矩阵分治法
将矩阵A,B和C中每一矩阵都分块成为4个大小相等的子矩阵,每个子矩阵都是n/2×n/2的方阵。由此可将方程C=A×B重写为:
C11=A11B11+A12B21
C12=A11B12+A12B22
C21=A21B11+A22B21
C22=A21B12+A22B22
计算2个n阶方阵的乘积转化
为计算8个n/2阶方阵的乘积和4个n/2阶方阵的加法
T(n)=8T(n/2)+cn2
T(1)=1
解仍然属于O(n3)

Strassen矩阵乘法
M1=A11(B12 - B22)
M2=(A11+A12)B22
M3=(A21+A22)B11
M4=A22(B21-B11)
M5=(A11+A22)(B11+B22)
M6=(A12-A22)(B21+B22)
M7=(A11-A21)(B11+B12)
算法只用了7次乘法运算,但增加了加、减法的运算次数10次。
C11=M5+M4-M2+M6
C12=M1+M2
C21=M3+M4
C22=M5+M1-M3-M7
用了7次对于n/2阶矩阵乘积的递归调用和18次n/2阶矩阵的加减运算。
T(n)=7T(n/2)+kn2
T(1)=1
解为T(n)∈O(nlog7)≈O(n2.81)。

最近点对问题

先将x1,x2,..,xn排好序,
然后,用一次线性扫描就可以找出最接近点对。
这种方法计算时间主要花在排序上,在排序算法中已经证明,时间复杂度为O(nlogn)。
然而这种方法无法直接推广到二维的情形。

对这种一维的简单情形,我们还是尝试用分治法来求解,并希望能推广到二维的情形。
假设我们用x轴上某个点m将S划分为2个子集S1和S2,
使得S1={x∈S|x≤m}; S2={x∈S|x>m}。


图片4.jpg

递归地在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d=min{|p1-p2|,|q1-q2|},S中的最近点对 或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2, |S1|=k, |S2|=n-k。


图片3.jpg

注意:如果{p3,q3}是最近点对, p3,q3 一定都在[m-d, m+d]中
随意划分: T(n) = T(k)+T(n-k) +O(n)
其中O(n) 为划分成两个子集的开销

该算法的分割步骤和合并步骤总共耗时O(n)。
因此,理想状态下, 找到中位元素进行划分
算法耗费的计算时间T(n)满足的递归方程为:


图片2.png

解得T(n)=O(nlog n)
前提是平衡点划分!
二维:


图片5.png

递推式
T(n) = 2T(n/2) + O(n)
得到T(n)属于O(nlog n)。

凸包问题

1 将点按x轴升序排列
2 找出最左点Pi和最右点Pj
(对应于图例中的P3 ,P6, 它们一定是该集合的凸包顶点)
3 Pi到Pj 的直线将凸包分成上/下包
4 递归地构造上包与下包
5.递归构造上包:
寻找距离直线 P1Pn 的左侧最远点Pmax
Pmax是凸包上的顶点
P1PmaxPn形成4个区域,顶点在四个区域外离边界距离最远
用同样的方法处理上包中的2个区域S1与S2


6.PNG

算法的复杂度为:
1.排序: O(n log n)
2.递归构造上包与下包 , 类同于快速排序
T(n)=2T(n/2)+O(n)----平均O(n log n)
T(n)=T(n-1)+O(n)----最坏O(n^2)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,341评论 0 2
  • 排序算法说明 (1)排序的定义:对一序列对象根据某个关键字进行排序; 输入:n个数:a1,a2,a3,…,an 输...
    code武阅读 658评论 0 0
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,183评论 0 52
  • 2017年3月28日,提交的拜师申请,刚刚好半年,参加过两次线下培训班(弟子免费)——5月20日的《演讲大师班》和...
    金津乐道阅读 205评论 0 0
  • 我生活在2018年我今年29岁,我姓秦名朽骨。这个名字有些奇怪,听爷爷奶奶说:给我取这个名字是因为,我出生时手...
    Tina睡着了阅读 173评论 0 0