分治法(Divide and Conquer)怎麼用?

分治法的思想是什麼?

給定一個問題集合,大小爲n,將它劃分紅a個大小爲 n/b 的小問題,而後組合每一個子問題的結果,遞歸的解決每一個小問題,直到最後的問題被解決算法

a >=1 b>1 。 解決時間爲 T(n)=aT(n/b)+O(合併須要的時間)數組

使用分治法去解決Convex Hull

convex hull定義

能夠定義到更高維,這裏添加的是更簡單的條件bash

在二維平面上給定一個集合S

S=\lbrace(x_i,y_i)|i=1,2,3,..,n\rbrace

假如任意兩個點x座標不一樣,y座標不一樣,同時不會出現三點共線的狀況,定義可以包含所有點的最小多邊形爲ConvexHux,簡寫爲CH(S)
定義它的邊界爲按照順時針順序開始的雙向列表ui

暴力方式來解決convex hull問題

鏈接任意的兩個點,構建一條邊,而後看是否全部的點都在這條邊的某一側,若是都在一側,那麼它就是,不然不是。
一共有n個點,那麼獲得的邊數爲n^2,同時要去檢驗全部的點是否在某一側,那麼總共的耗時爲 O(n^3)spa

分治法解決方案

先按照x軸座標給全部的點排序,這樣的耗時爲O(nlgn)
選定一個點的橫座標x,將全部的點分紅兩部分:CH(A)和CH(B),分別解決CH(A)和CH(B),而後再合併C(A)和CH(B).net

怎麼去合併

一樣的能夠按照粗暴的思路來解決,就是去看全部的兩個CH的全部頂點連線,而後看是否全部的點都在它的一側。
注意:找到兩邊都只最大的y座標來做爲一條邊會出現問題 3d

以找到上邊界爲例,爲方便作一條直線使得它恰好切割兩個CH,鏈接兩個CH的點a_1,b_1,這兩點據選取的軸線x之間的距離在兩個圖形中均最近。它與選定的軸交於藍線與選定實線軸交點處。code

而後按照順時針順序,移動 b_1b_3,一樣獲得紫線與實線的交點
能夠發現它在藍線之下,這時候它是沒法做爲邊的,因而b仍然取 b_1,同時a按照逆時針方向移到 a_4,交點爲橙色線和實線

能夠發現它比藍線和實線的交點更高,因而它更適合,這個時候,再按照順時針移動 b_1b_3
能夠看到 b_1更加適合,因而a再逆時針移動 a_3

能夠看到仍然是 ( a_4, b_1)仍然是最好的選擇,至此a和b都找到了最佳的選擇。 算法實現找到上邊界僞代碼爲:

i=1
 j=1
 while (y(i, j + 1) > y(i, j) or y(i − 1, j) > y(i, j))
     if (y(i, j + 1) > y(i, j)) // move right  clockwise
         j = j + 1( mod q) //右邊q個節點
     else
         i = i − 1( mod p) // move left  anti-clockwise 左邊p個節點
return (ai, bj ) as upper tangent
複製代碼

p+q=ncdn

能夠看到這種方式最多遍歷完n個點,耗時爲O(n),整個過程耗時爲:blog

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

合併以後如何刪掉不應有的連線?

選取新增的上邊接(a_4,b_1),相似的下邊界(a_2,b_2),沿着(a_4,b_1),按照順時針的方向,碰到邊(b_1,b_3),(b_3,b_2),此時的點恰好到了下邊界,而後沿着下邊界(a_2,b_2),繼續順時針,知道a_4即獲得合併後的邊界

使用分治法解決找到數組中全部元素數值大小的中間值

最明顯的方式就是先排序,而後就直接獲取了,排序算法的時間爲O(nlgn)。而使用分治法可以達到O(n)的時間,思路以下。

Select(S, i) //i是要找的元素
 Pick x ∈ S  //選取一個元素
 Compute k = rank(x) //找到x在隊列中的位置
 B = {y ∈ S|y<x}
 C = {y ∈ S|y>x}
 if k = i
     return x //x的順序剛好和找的位置是相同的,直接返回
 else if k>i
     return Select(B, i) 
 else if k<i
    return Select(C, i − k)
複製代碼

對於選擇x來說,若是選擇的很差,好比總共n個,剛好選擇的是第n-1個,而後是第n-2個,依次類推,總共須要n/2次,每次挑選原數的集合的時候也是O(n),那麼若是x選取很差整個的時間爲O(n^2)

若是選取x的值?

將S分紅5列,這樣它就是有多行數據,一共5列的二維數組,把每列進行排序,最大的元素在上頭,最後x的取值爲全部列中間取值的中間的值

方便畫有行列交換

通過這麼劃分,能夠看到

  • 小於X的取值元素數量至少爲:3(n/10-2)
  • 大於X的取值元素數量至少爲:3(n/10-2)

這裏取 n/10的上邊界。能夠看到一共有 n/5 行,而有一半的行都會存在小於X的數,每行都會有3個,除了包含X的那一行和不足5個元素的最後一行

能夠獲得整個的耗時爲

T(n)=\lbrace^{O(1)\space for \space x<=140}_{T(n/5)+T(7n/10+6)+O(n)\space for\space x>140}

全部的除法所有上取整

T(n/5) 是找到全部行中的中間元素所須要的時間;T(7n/10+6)表示迭代須要的時間,每執行完以後,剩下的數量機n-3(n/10-6);O(n)表示給全部列排序的時間,一列只有5個元素,顯然是常量時間,一共有 n/5 列全部的就是O(n)

對於迭代的部分有

T(n)<cn/5+c+cn7/10+6c+O(n)
    <cn+7c+an-cn/10
複製代碼

若7c+an-cn/10<=0

70c+10an-cn<=0
c>=70c/n+10a
當n>=140時,有
c>=c/2+10a
即c>=20a,成立
複製代碼

有T(n)<cn ,此時總耗時爲O(n)。

相關文章
相關標籤/搜索