一,介紹
分治演算法主要包含兩個步驟:分、治。分,就是遞迴地將原問題分解成小問題;治則是:在解決了各個小問題之後(各個擊破之後)合併小問題的解,從而得到整個問題的解
二,分治遞迴表示式
分治演算法一般都可以寫出乙個遞迴表示式;比如經典的歸併排序的遞迴表示式:t(n)=2t(n/2)+o(n)
t(n)代表整個原問題,採用了分治解決方案後,它可以表示成:
①分解成了兩個規模只有原來一半(n/2)的子問題:t(n/2)
②當解決完這兩個子問題t(n/2)之後,再合併這兩個子問題需要的代價是 o(n)
遞迴表示式的解就是該演算法的時間複雜度。關於某些特定形式的遞迴表示式,求解時,是可以直接套公式的:
t(n)=at(n/b)+θ(n^k) 表示將原問題分解成 a 個 規模大小為 n/b 的子問題,合併這 a 個子問題的代價是 θ(n^k) (n^k 表示 n 的 k 次方)
t(n)的解有以下三種情況:
1) t(n)=o(n^logba) 當 a > bk 時
2) t(n)=o(nk logn) 當 a = bk 時
3) t(n)=o(nk) 當 a < bk 時
三,分治演算法的一些例項分析
①最近點問題,參考《資料結構與演算法分析》mark allen wiess著 第10章
問題描述:在乙個平面上分布著若干個點,點與點之間的距離公式為:[(x1-x2)2 + (y1-y2)2]1/2
找出,距離最小的那兩個點
假設平面上有n個點,這n個點之間共有 1+2+3+……+(n-1) = n(n-1)/2 個距離,採用窮舉,時間複雜度為o(n^2);而採用分治則可以做到o(nlogn)
那如何應用分治呢?
首先將n個點按照 x軸座標進行排序,排序演算法的時間複雜度為o(nlogn),故相對於窮舉而言,它不影響總是時間複雜度。因為o(nlogn) << o(n^2)(遠遠小於)
按x軸座標排序後,可以劃一條垂直於x軸的線,將所有的點劃分成兩半。那麼,點與點之間的距離就會出現三種情況:
a)兩個點完全處於垂線的左邊,那麼這兩點的距離不會越過垂線,這類距離記為 dl
b)兩個點完全處於垂線的右邊,那麼這兩點的距離不會越過垂線,這類距離記為 dr
c)兩個點乙個在垂線的左邊,乙個在垂線的右邊,因此這兩個的距離會橫跨垂線
這種劃分思想,在求解:最大子串行的和 時,也可以採用。
設 mind = min,即mind是 a) 和 b) 這兩種情況下的所有距離中最小的那個距離。
那麼,可以用數學證明:處於[-mind, mind]這個範圍內的點平均只有 o(sqrt(n))個。
而sqrt(n)個點,一共有 o(n)個距離對,因為n個點一共有n(n-1)/2,即o(n^2)個距離對
這樣,我們可以將處於 c) 中的點對距離 採用窮舉來查詢出最小的距離,複雜度為o(n)
而,處於a) 和 b) 中的點可以 繼續進行遞迴劃分。
從而,遞迴表示式為: t(n)=2t(n/2)+o(n) ,而這個表示式的解為:t(n)=o(nlogn)
也就是說,採用了分治,成功地將原問題從o(n^2) 降低為 o(nlogn)
②k選擇問題
問題描述:給出n個數,找出其中第k小的元素
如果直接用窮舉,一共需要比較k*n次,當k與n有關時,比如k是中位數(k=n/2),時間複雜度為o(n^2).
而採用分治,則可把複雜度降低為o(n)
首先在n個數選出乙個樞軸元素,將比樞軸元素的元素放到 樞軸元素的右邊,將比樞軸元素小的元素放到樞軸元素的左邊。這樣,把n個數,分成了兩部分,一部分,記為s(1) 它們都比樞軸大,另一部分記為s(2),它們都比樞軸小。這就是分治 的 分。
假設一種理想的情況:樞軸元素 基本位於中間值,即它 總是將原陣列劃分成兩個兩個大小基本相等的子陣列:s(1) 和 s(2)
要求解第k小的元素,有三種情況:
a)若 k < |s(1)|,說明:第k小的元素位於 s(1)這個子陣列中。其中,|s(1)| 表示 s(1) 陣列中元素的個數。
b) 若 k == |s(1)| + 1,說明:第k小的元素,剛好是樞軸元素
c) 否則,第k個的元素位於 s(2)子陣列中
如果是情況 a) 或者 情況 c) ,可以繼續遞迴分解子陣列。
分解問題之後:將n個元素,分成了兩個 n/2 個元素的子陣列,只需要在其中乙個子陣列中進行查詢即可,使用窮舉查詢,複雜度為o(n/2)。
遞迴表示式: t(n)=t(n/2)+o(n/2),這個遞迴表示式的解為o(n)
這說明,採用分治,可以將k選擇問題的時間複雜度降低為o(n)
順便說一句,這與快速排序的劃分非常的相似,只不過快速排序需要處理兩個子陣列(對劃分的兩個子陣列分別進行快速排序)。而這裡只需要處理其中某乙個子陣列,因為若第k小元素處於s(1)子陣列中,那麼它一定不會在s(2)子陣列中了,因此我們就不需要再處理s(2)子陣列了。
原文:
分治演算法思想
1.分解 對這k個子問題分別求解。如果子問題的規模仍然不夠小,則再劃分為k個子問題,如此遞迴的進行下去,直到問題規模足夠小,很容易求出其解為止。2.合併 將求出的小規模的問題的解合併為乙個更大規模的問題的解,自底向上逐步求出原來問題的解。3.分治演算法的使用條件 分治法所能解決的問題一般具有以下幾個...
演算法思想 分治演算法
分而治之 大問題能夠拆成相似的小問題,記住這些小問題需要具有相似性。而後將小問題的每個解合成為大問題的解。所以說大問題如何拆,小問題如何合併才是這個演算法最主要的乙個思想。實際上很多演算法如貪心演算法,動態規劃等等都是要求把大問題拆成小問題。而分治演算法的重要一點就是要適用於能夠重新把小問題的解合併...
分治演算法介紹
分治演算法是一種很重要的演算法。字面上的解釋是 分而治之 就是把乙個複雜的問題分解成兩個或更多個相同或相似的問題,再把子問題分成更小的問題。直到最後的子問題可以直接求解阿,原問題的解即子問題的解的合併。這個技巧是很多高效演算法的基礎,如排序演算法 快速排序,歸併排序 博立葉變換 快速博立葉變換 分子...