常用演算法 — 分治法

來源:互聯網
上載者:User

 

1、分治法的基本思想 

任何一個可以用電腦求解的問題所需的計算時間都與其規模N有關。問題的規模越小,越容易直接求解,解題所需的計算時間也越少。例如,對於n個元素的排序 問題,當n=1時,不需任何計算;n=2時,只要作一次比較即可排好序;n=3時只要作3次比較即可,…。而當n較大時,問題就不那麼容易處理了。要想直 接解決一個規模較大的問題,有時是相當困難的。 

分治法的設計思想是,將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。 

如果原問題可分割成k個子問題(1<k≤n),且這些子問題都可解,並可利用這些子問題的解求出原問題的解,那麼這種分治法就是可行的。由分治法產 生的子問題往往是原問題的較小模式,這就為使用遞迴技術提供了方便。在這種情況下,反覆應用分治手段,可以使子問題與原問題類型一致而其規模卻不斷縮小, 最終使子問題縮小到很容易直接求出其解。這自然導致遞迴過程的產生。分治與遞迴像一對孿生兄弟,經常同時應用在演算法設計之中,並由此產生許多高效演算法。 

2、分治法的適用條件 

分治法所能解決的問題一般具有以下幾個特徵: 

(1)該問題的規模縮小到一定的程度就可以容易地解決; 

(2)該問題可以分解為若干個規模較小的相同問題,即該問題具有最優子結構性質; 

(3)利用該問題分解出的子問題的解可以合并為該問題的解; 

(4)該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公用的子子問題。 

上述的第一條特徵是絕大多數問題都可以滿足的,因為問題的計算複雜性一般是隨著問題規模的增加而增加;第二條特徵是應用分治法的前提,它也是大多數問題可 以滿足的,此特徵反映了遞迴思想的應用;第三條特徵是關鍵,能否利用分治法完全取決於問題是否具有第三條特徵,如果具備了第一條和第二條特徵,而不具備第 三條特徵,則可以考慮貪進法或動態規劃法。第四條特徵涉及到分治法的效率,如果各子問題是不獨立的,則分治法要做許多不必要的工作,重複地解公用的子問 題,此時雖然可用分治法,但一般用動態規劃法較好。 

3、分治法的基本步驟 

分治法在每一層遞迴上都有三個步驟: 

(1)分解:將原問題分解為若干個規模較小,相互獨立,與原問題形式相同的子問題; 

(2)解決:若子問題規模較小而容易被解決則直接解,否則遞迴地解各個子問題; 

(3)合并:將各個子問題的解合并為原問題的解。 

它的一般的演算法設計模式如下: 

Divide_and_Conquer(P) 

if |P|≤n0 

then return(ADHOC(P)) 

將P分解為較小的子問題P1、P2、…、Pk 

for i←1 to k 

do 

yi ← Divide-and-Conquer(Pi)        △ 遞迴解決Pi 

T ← MERGE(y1,y2,…,yk)          △ 合并子問題 

Return(T) 

其中 |P| 表示問題P的規模;n0為一閾值,表示當問題P的規模不超過n0時,問題已容易直接解出,不必再繼續分解。ADHOC(P)是該分治法中的基本子演算法,用於直接解小規模的問題P。因此,當P的規模不超過n0時,直接用演算法ADHOC(P)求解。 

演算法MERGE(y1,y2,…,yk)是該分治法中的合并子演算法,用於將P的子問題P1、P2、…、Pk的相應的解y1、y2、…、yk合并為P的解。 

根據分治法的分割原則,原問題應該分為多少個子問題才較適宜?各個子問題的規模應該怎樣才為適當?這些問題很難予以肯定的回答。但人們從大量實踐中發現, 在用分治法設計演算法時,最好使子問題的規模大致相同。換句話說,將一個問題分成大小相等的k個子問題的處理方法是行之有效。許多問題可以取k=2。這種 使子問題規模大致相等的做法是出自一種平衡子問題的思想,它幾乎總是比子問題規模不等的做法要好。 

分治法的合并步驟是演算法的關鍵所在。有些問題的合并方法比較明顯,有些問題合并方法比較複雜,或者是有多種合并方案;或者是合并方案不明顯。究竟應該怎樣合并,沒有統一的模式,需要具體問題具體分析。 

【問題】    大整數乘法 

問題描述: 

通常,在分析一個演算法的計算複雜性時,都將加法和乘法運算當作是基本運算來處理,即將執行一次加法或乘法運算所需的計算時間當作一個僅取決於電腦硬體處理速度的常數。 

這個假定僅在電腦硬體能對參加運算的整數直接表示和處理時才是合理的。然而,在某些情況下,我們要處理很大的整數,它無法在電腦硬體能直接表示的範圍 內進行處理。若用浮點數來表示它,則只能近似地表示它的大小,計算結果中的有效數字也受到限制。若要精確地表示大整數並在計算結果中要求精確地得到所有位 數上的數字,就必須用軟體的方法來實現大整數的算術運算。 

請設計一個有效演算法,可以進行兩個n位大整數的乘法運算。 

設X和Y都是n位的二進位整數,現在要計算它們的乘積XY。我們可以用小學所學的方法來設計一個計算乘積XY的演算法,但是這樣做計算步驟太多,顯得效率較 低。如果將每2個1位元的乘法或加法看作一步運算,那麼這種方法要作O(n2)步運算才能求出乘積XY。下面我們用分治法來設計一個更有效大整數乘積算 法。 

 

圖6-3 大整數X和Y的分段 

我們將n位的二進位整數X和Y各分為2段,每段的長為n/2位(為簡單起見,假設n是2的冪),6-3所示。 

由此,X=A2n/2+B,Y=C2n/2+D。這樣,X和Y的乘積為: 

XY=(A2n/2+B)(C2n/2+D)=AC2n+(AD+CB)2n/2+BD    (1) 

如果按式(1)計算XY,則我們必須進行4次n/2位整數的乘法(AC,AD,BC和BD),以及3次不超過n位的整數加法(分別對應於式(1)中的加 號),此外還要做2次移位(分別對應於式(1)中乘2n和乘2n/2)。所有這些加法和移位共用O(n)步運算。設T(n)是2個n位整數相乘所需的運算 總數,則由式(1),我們有: 

             (2) 

由此可得T(n)=O(n2)。因此,用(1)式來計算X和Y的乘積並不比小學生的方法更有效。要想改進演算法的計算複雜性,必須減少乘法次數。為此我們把XY寫成另一種形式: 

XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD        (3) 

雖然,式(3)看起來比式(1)複雜些,但它僅需做3次n/2位整數的乘法(AC,BD和(A-B)(D-C)),6次加、減法和2次移位。由此可得: 

               (4) 

用解遞迴方程的套用公式法馬上可得其解為T(n)=O(nlog3)=O(n1.59)。利用式(3),並考慮到X和Y的符號對結果的影響,我們給出大整數相乘的完整演算法MULT如下: 

function MULT(X,Y,n); {X和Y為2個小於2n的整數,返回結果為X和Y的乘積XY} 

begin 

S=SIGN(X)*SIGN(Y); {S為X和Y的符號乘積} 

X=ABS(X); 

Y=ABS(Y); {X和Y分別取絕對值} 

if n=1 then 

if (X=1)and(Y=1) then return(S) 

else return(0) 

else begin 

A=X的左邊n/2位; 

B=X的右邊n/2位; 

C=Y的左邊n/2位; 

D=Y的右邊n/2位; 

ml=MULT(A,C,n/2); 

m2=MULT(A-B,D-C,n/2); 

m3=MULT(B,D,n/2); 

S=S*(m1*2n+(m1+m2+m3)*2n/2+m3); 

return(S); 

end; 

end; 

上述二進位大整數乘法同樣可應用於十進位大整數的乘法以提高乘法的效率減少乘法次數。 

【問題】    最接近點對問題 

問題描述: 

在應用中,常用諸如點、圓等簡單的幾何對象代表現實世界中的實體。在涉及這些幾何對象的問題中,常需要瞭解其鄰域中其他幾何對象的資訊。例如,在空中交通 控制問題中,若將飛機作為空白間中移動的一個點來看待,則具有最大碰撞危險的2架飛機,就是這個空間中最接近的一對點。這類問題是計算幾何學中研究的基本問 題之一。下面我們著重考慮平面上的最接近點對問題。 

最接近點對問題的提法是:給定平面上n個點,找其中的一對點,使得在n個點的所有點對中,該點對的距離最小。 

嚴格地說,最接近點對可能多於1對。為了簡單起見,這裡只限於找其中的一對。 

這個問題很容易理解,似乎也不難解決。我們只要將每一點與其他n-1個點的距離算出,找出達到最小距離的兩個點即可。然而,這樣做效率太低,需要O(n2)的計算時間。我們能否找到問題的一個O (nlogn)演算法。 

這個問題顯然滿足分治法的第一個和第二個適用條件,我們考慮將所給的平面上n個點的集合S分成2個子集S1和S2,每個子集中約有n/2個點,然後在每個 子集中遞迴地求其最接近的點對。在這裡,一個關鍵的問題是如何?分治法中的合并步驟,即由S1和S2的最接近點對,如何求得原集合S中的最接近點對,因 為S1和S2的最接近點對未必就是S的最接近點對。如果組成S的最接近點對的2個點都在S1中或都在S2中,則問題很容易解決。但是,如果這2個點分別在 S1和S2中,則對於S1中任一點p,S2中最多隻有n/2個點與它構成最接近點對的候選者,仍需做n2/4次計算和比較才能確定S的最接近點對。因此, 依此思路,合并步驟耗時為O(n2)。整個演算法所需計算時間T(n)應滿足: 

T(n)=2T(n/2)+O(n2) 

它的解為T(n)=O(n2),即與合并步驟的耗時同階,顯示不出比用窮舉的方法好。從解遞迴方程的套用公式法,我們看到問題出在合并步驟耗時太多。這啟發我們把注意力放在合并步驟上。 

為了使問題易於理解和分析,我們先來考慮一維的情形。此時S中的n個點退化為x軸上的n個實數x1、x2、…、xn。最接近點對即為這n個實數中相差最小 的2個實數。我們顯然可以先將x1、x2、…、xn排好序,然後,用一次線性掃描就可以找出最接近點對。這種方法主要計算時間花在排序上,因此如在排序算 法中所證明的,耗時為O(nlogn)。然而這種方法無法直接推廣到二維的情形。因此,對這種一維的簡單情形,我們還是嘗試用分治法來求解,並希望能推廣 到二維的情形。 

假設我們用x軸上某個點m將S劃分為2個子集S1和S2,使得S1={x∈S | x≤m};S2={x∈S | x>m}。這樣一來,對於所有p∈S1和q∈S2有p<q。 

遞迴地在S1和S2上找出其最接近點對{p1,p2}和{q1,q2},並設δ=min{|p1-p2|,|q1-q2|},S中的最接近點對或者是{p1,p2},或者是{q1,q2},或者是某個{p3,q3},其中p3∈S1且q3∈S2。1所示。 

 

圖1 一維情形的分治法 

我們注意到,如果S的最接近點對是{p3,q3},即 | p3-q3 | < δ,則p3和q3兩者與m的距離不超過δ,即 | p3-m | < δ,| q3-m | < δ,也就是說,p3∈(m-δ,m),q3∈(m,m+δ)。由於在S1中,每個長度為δ的半閉區間至多包含一個點(否則必有兩點距離小於δ),並且m是 S1和S2的分割點,因此(m-δ,m)中至多包含S中的一個點。同理,(m,m+δ)中也至多包含S中的一個點。由圖1可以看出,如果(m-δ,m)中 有S中的點,則此點就是S1中最大點。同理,如果(m,m+δ)中有S中的點,則此點就是S2中最小點。因此,我們用線性時間就能找到區間(m-δ,m) 和(m,m+δ)中所有點,即p3和q3。從而我們用線性時間就可以將S1的解和S2的解合并成為S的解。也就是說,按這種分治策略,合并步可在O(n) 時間內完成。這樣是否就可以得到一個有效演算法了呢? 

還有一個問題需要認真考慮,即分割點m的選取,及S1和S2的劃分。選取分割點m的一個基本要求是由此匯出集合S的一個線性分割,即S=S1∪S2 ,S1∩S2=Φ,且S1 {x | x≤m};S2 {x | x>m}。容易看出,如果選取m=[max(S)+min(S)]/2,可以滿足線性分割的要求。選取分割點後,再用O(n)時間即可將S劃分成 S1={x∈S | x≤m}和S2={x∈S | x>m}。然而,這樣選取分割點m,有可能造成劃分出的子集S1和S2的不平衡。例如在最壞情況下,|S1|=1,|S2|=n-1,由此產生的分 治法在最壞情況下所需的計算時間T(n)應滿足遞迴方程: 

T(n)=T(n-1)+O(n) 

它的解是T(n)=O(n2)。這種效率降低的現象可以通過分治法中“平衡子問題”的方法加以解決。也就是說,我們可以通過適當選擇分割點m,使S1和 S2中有大致相等個數的點。自然地,我們會想到用S的n個點的座標的中位元來作分割點。在選擇演算法中介紹的選取中位元的線性時間演算法使我們可以在O(n) 時間內確定一個平衡的分割點m。 

至此,我們可以設計出一個求一維點集S中最接近點對的距離的演算法pair如下。 

Float pair(S); 

{    if | S | =2    δ= | x[2]-x[1] |      /*x[1..n]存放的是S中n個點的座標*/ 

else 

{    if ( | S | =1)    δ=∞ 

     else 

{    m=S中各點的座標值的中位元; 

       構造S1和S2,使S1={x∈S | x≤m},S2={x∈S | x>m}; 

δ1=pair(S1); 

         δ2=pair(S2); 

         p=max(S1); 

         q=min(S2); 

         δ=min(δ1,δ2,q-p); 

} 

return(δ); 

} 

由以上的分析可知,該演算法的分割步驟和合并步驟總共耗時O(n)。因此,演算法耗費的計算時間T(n)滿足遞迴方程: 

 

解此遞迴方程可得T(n)=O(nlogn)。 

 

【問題】迴圈賽議程表 

問題描述:設有n=2k個運動員要進行網球迴圈賽。現要設計一個滿足以下要求的比賽議程表: 

(1)每個選手必須與其他n-1個選手各賽一次; 

(2)每個選手一天只能參賽一次; 

(3)迴圈賽在n-1天內結束。 

請按此要求將比賽議程表設計成有n行和n-1列的一個表。在表中的第i行,第j列處填入第i個選手在第j天所遇到的選手。其中1≤i≤n,1≤j≤n-1。 

按分治策略,我們可以將所有的選手分為兩半,則n個選手的比賽議程表可以通過n/2個選手的比賽議程表來決定。遞迴地用這種一分為二的策略對選手進行劃分,直到只剩下兩個選手時,比賽議程表的制定就變得很簡單。這時只要讓這兩個選手進行比賽就可以了。 

 

                           1    2    3    4    5    6    7 

                         1    2    3    4    5    6    7    8 

                         2    1    4    3    6    7    8    5 

                         3    4    1    2    7    8    5    6 

             1    2    3          4    3    2    1    8    5    6    7 

           1    2    3    4          5    6    7    8    1    4    3    2 

   1          2    1    4    3          6    5    8    7    2    1    4    3 

1    2          3    4    1    2          7    8    5    6    3    2    1    4 

2    1          4    3    2    1          8    7    6    5    4    3    2    1 

(1)            (2)                    (3) 

圖1 2個、4個和8個選手的比賽議程表 

圖1所列出的正方形表(3)是8個選手的比賽議程表。其中左上方與左下角的兩小塊分別為選手1至選手4和選手5至選手8前3天的比賽議程。據此,將左上方 小塊中的所有數字按其相對位置抄到右下角,又將左下角小塊中的所有數字按其相對位置抄到右上方,這樣我們就分別安排好了選手1至選手4和選手5至選手8在 後4天的比賽議程。依此思想容易將這個比賽議程表推廣到具有任意多個選手的情形。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.