分治算法

Divide-and-Conquer算法的设计

设计过程分为三个阶段:

Divide:整个问题划分为多个子问题

Conquer:求解各子问题(递归调用正设计的算法)

Merge:合并子问题的解,形成原始问题的解

下面是几道小题使用分治算法求解的思路。

1黑白点对

题目:

给定平面上有n个白点和n个黑点,任意三点不共线,试实际一个分治算法将每个白点与一个黑点相连,是所有连线互不相交。

思路:

将所有2n个点点按照x有小到大排序,以一条垂直于x轴的线将这些点分为大小均为n的左右两部分,左右两部分递归的进行黑白点对的匹配,由于每部分分到的黑点数与白点数不一定相等,最终返回的每部分都是互不相交的黑白点对连线以及一些单独的黑点,或者是互不相交的黑白点对连线以及一些单独的白点。

在合并时,若两部分剩余的点都是黑色或都是白色,则合并完成。

若一部分剩余的是黑点,另一部分剩余的是白点,则将这些点匹配连线。每次新连接一条线时,若并不与其他线相交,则连接下一对;若与其他k对相交,可以通过k-1次交换使其不再交叉(由于不存在任意三点共线,所以必然可以通过有限次交换使其互不相交),连接下一对。直到单独的黑点或者白点全部连接完毕。

算法设计:

Divide:按照横坐标,将所有点分为等量的左右两部分。

Conquer:递归的将左右两部分进行黑白点对的匹配。当某部分中只有一个点或两个同色的点时,直接返回;有两个不同色的点时,将他们匹配。

Merge:左右两部分中若有某部分黑白点完全匹配了,直接合并,返回;左右两部分没有匹配的单独点同色,直接合并,返回;将左右两部分没有匹配的点异色,依次匹配,若存在交叉,则可以通过与交叉线段有限次交换使其互不相交,当所有某侧单独的点都完成匹配,返回。

时间复杂度分析:

设该算法的时间复杂度为T(2n),合并时,左右两侧单独的点最多进行n次连线,每次连线时最多与与其相交的n-1条线段进行交换,时间复杂度为O(n^2)。

T(n)=2T(n/2)+O(n^2).

逐步递推得到时间复杂度T(n)=O(n^2).

2求最大连续子数组

题目:

给定一个数组A[1:n],数组元素由实数构成,求A的连续子数组,使得此子数组的和最大。如:A={-2,-5,6,-2,-3,1,5,-6},结果为{6,-2,-3,1,5},和为7。设计一个分治算法,求A[1:n]的和最大连续子数组

思路:

采用二分的方法将数组从中间分为左右两个子数组,则最大子数组必然出现在以下三种情况之一:

1)完全位于左边的数组中。

2)完全位于右边的数组中。

3)跨越中点,包含左右数组中靠近中点的部分。

递归将左右子数组再分别分成两个数组,直到子数组中只含有一个元素,退出每层递归前,返回上面三种情况中的最大值。

算法设计:

Divide:将数组A划分为左右两个子数组AL和AR。

Conquer:递归的求解AL和AR的最大连续子数组。若数组中只有一个数字,最大连续子数组为这个数字本身。

Merge:AL和AR的最大连续子数组的和分别为MaxLeftSum,MaxRightSum。设从AL最右端开始的连续子序列的最大和为MaxLeftBorderSum,从AR最左端开始的连续子序列的最大和为MaxRightBorderSum,那么跨越中点的最大连续子数组的和为MaxLeftBorderSum+MaxRightBorderSum。返回MaxLeftSum,MaxRightSum,MaxLeftBorderSum+MaxRightBorderSum这三者的最大值。

时间复杂度分析:

设该算法的时间复杂度为T(n),则:

T(n)=2T(n/2)+O(n),且T(1)=1.

逐步递推得到时间复杂度T(n)=O(nlogn).

3英文字母编码

题目:

将26个英文字母进行编码,‘A’编码为‘1’,‘B’编码为‘2’,……,‘Z’编码为‘26’。那么给定一个数字序列可以对其进行解码,但解码不唯一。比如给定数字序列“234”,可以解码为“2-3-4”,对应“BCD”;也可以解码为“23-4”,对应“WD”。设计一个分治算法,对于给定的数字序列LIST,求出给数字序列有几种解码方式。

思路:

编码为1~26,所以数字有以下几种情况:

数字0必须与它前面的1或2一起编码,只有一种编码情况;数字1可单独编码,也可与其后面的数字一起编码,通常有两种情况,但当后面跟着10或20时,只能编码为A;数字2可单独编码,也可与其后面的数字0~6一起编码,但当后面跟着7、8、9、10、20时,只能编码为B;数字3~9前没有1或2时只有一种编码情况。

可以递归的将序列LIST二分,直到每个子序列中只有一个数字,此时子序列的解码方式为1,合并时考虑合并处两个数字是否有更多的解码方式。

算法设计:

Divide:将序列LIST划分为左右两个子序列LISTL和LISTR。

Conquer:递归的求解LISTL和LISTR的解码方式。若序列中只有一个数字,返回解码方式为1。

Merge:将LISTL和LISTR的解码方式数相乘,得到res。再考虑合并处的两个数字,即LISTL的最右数字n1与LISTR的最左数字n2,若n1等于1,n2不为0,则将res乘以2;若n1等于2,n2为1~6,则将res乘以2;其余情况res不变。将得到的res返回。

时间复杂度分析:

设该算法的时间复杂度为T(n),则:

T(n)=2T(n/2)+O(n),且T(1)=1.

逐步递推得到时间复杂度T(n)=O(nlogn).

4求逆序数

题目:

设A[1:n]是由不同实数组成的数组,如果iA[j],则称实数对(A[i],A[j])是该数组的一个反序。如,若A=[3,5,2,4],则该数组存在3个反序(3,2)、(5,2)和(5,4)。设计一个分治算法,求逆序数。

思路:

类似于归并排序算法。先将数组从中间分成两个部分,然后分别递归左半部分和右半部分,再合并排好序的左右两个部分,从而统计逆序对数。

对于两个排好序的数组AL和AR,初始时分别设置指针p1、p2在数组最左端,比较AL[p1]与AR[p2]的大小:如果AL[p1]>AR[p2],那么显然AL中AL[p1]及其后面的所有元素都能与AR[p2]构成逆序对,记录这个数并将p2右移;否则将p1右移,当完成两个数组的遍历后就得到了这两个数组间的逆序数。

算法设计:

Divide:将数组A划分为左右两个子数组AL和AR。

Conquer:递归的求解AL和AR的逆序数。若数组中只有一个数字,则返回逆序数为0。

Merge:AL和AR的逆序数分别为sum1、sum2。AL和AR在之前的合并中已经按从小到大的顺序排好序了,所以我们可以在一次对这两个数组的遍历中,将它们以归并排序的方法合并为A时,同时得到这两个数组间的逆序数sum3。A的逆序数为sum1+sum2+sum3。

时间复杂度分析:

每次都要将序列的的n个元素合并,时间复杂度为O(n)。

设该算法的时间复杂度为T(n),则:

T(n)=2T(n/2)+O(n),且T(1)=1.

逐步递推得到时间复杂度T(n)=O(nlogn).

5友谊点对

题目:

给定平面上n个点构成的集合S={p1,p2,……,pn}。如果存在便平行于坐标轴的矩形仅包含S中的两个点pi和pj(1<=i<j<=n),则称pi和pj为友谊点对。试设计一个分治算法统计S中友谊点对的个数。

算法设计:

预处理:将点集S中的所有点按照x有小到大排序。

Divide:将点集S用一条垂直于x轴的直线l:x=m划分为两个大小相等的子集SL和SR。

Conquer:递归的求解SL和SR中友谊点对数。若点集中点的数量为1,返回友谊点对数0;若点集中点的数量为2,这两个点一定为友谊点对,返回友谊点对数1。

Merge:S的友谊点对数=SL的友谊点对数+SR的友谊点对数+两点分别位于SL和SR的友谊点对数。两点分别位于SL和SR的友谊点对数的求法如下:

1)p0(x0,y0)为SL中最右点,以y=y0为界将SR分为上下两部分讨论。对于上半部分找出x最小的点A和y最小的点B,能与p0构成友谊点对的必然出现在以A、B为顶点的矩形区域中。

2)依次遍历横坐标在区间(xA,xB)中的点。能与p0构成友谊点对的,必然是横坐标依次增大同时纵坐标依次减小的(若横坐标增大的同时纵坐标也增大,后一个点与p0构成的矩形中会包含前一个点)。下半部分同理。

3)p1为SL中次右点,若y1>y0,则只需考虑y>y0的区域;反之,只需考虑y<y0的区域。对于pk,只需考虑SL中纵坐标与其相邻的两个点pi、pj的纵坐标所夹区域(yi,yj)。对于SL中的每个点重复上述两步,直到完全遍历。

时间复杂度分析:

设该算法的时间复杂度为T(n),则:

T(n)=2T(n/2)+f(n),且f(n)<=O(n^2).

所以T(n)=O(n^2).

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

推荐阅读更多精彩内容

  • 五大常用算法之一:分治算法 一、基本概念 在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就...
    鲍陈飞阅读 1,238评论 0 4
  • http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741...
    RavenX阅读 450评论 0 1
  • 分冶算法的基本思想是将原问题分解为几个规模较小的但类似原问题的子问题,递归地求解这些了问题,然后再合并这些子问题的...
    某昆阅读 1,627评论 0 6
  • 1、前言 本文是在阅读算法导论的时候做的一点记录。加上前段时间阅读了《计算机科学丛书:设计模式 可复用面向对象软件...
    BBH_Life阅读 364评论 0 0
  • 原来那不是骗人的。看到绝美的风景,真的会感动。 说笑了一整天,忙碌了一整天,洗漱之后背上自己的小包准备去前院陪...
    熙熙哈阅读 907评论 0 2