分治算法

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閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容

  • 五大常用算法之一:分治算法 一、基本概念 在計算機科學中,分治法是一種很重要的算法。字面上的解釋是“分而治之”,就...
    鮑陳飛閱讀 1,247評論 0 4
  • http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741...
    RavenX閱讀 461評論 0 1
  • 分冶算法的基本思想是將原問題分解為幾個規模較小的但類似原問題的子問題,遞歸地求解這些了問題,然后再合并這些子問題的...
    某昆閱讀 1,708評論 0 6
  • 1、前言 本文是在閱讀算法導論的時候做的一點記錄。加上前段時間閱讀了《計算機科學叢書:設計模式 可復用面向對象軟件...
    BBH_Life閱讀 371評論 0 0
  • 原來那不是騙人的。看到絕美的風景,真的會感動。 說笑了一整天,忙碌了一整天,洗漱之后背上自己的小包準備去前院陪...
    熙熙哈閱讀 948評論 0 2