給定一個問題集合,大小爲n,將它劃分紅a個大小爲 n/b 的小問題,而後組合每一個子問題的結果,遞歸的解決每一個小問題,直到最後的問題被解決算法
a >=1 b>1 。 解決時間爲 T(n)=aT(n/b)+O(合併須要的時間)數組
能夠定義到更高維,這裏添加的是更簡單的條件bash
假如任意兩個點x座標不一樣,y座標不一樣,同時不會出現三點共線的狀況,定義可以包含所有點的最小多邊形爲ConvexHux,簡寫爲CH(S)
定義它的邊界爲按照順時針順序開始的雙向列表ui
鏈接任意的兩個點,構建一條邊,而後看是否全部的點都在這條邊的某一側,若是都在一側,那麼它就是,不然不是。
一共有n個點,那麼獲得的邊數爲,同時要去檢驗全部的點是否在某一側,那麼總共的耗時爲
spa
先按照x軸座標給全部的點排序,這樣的耗時爲O(nlgn)
選定一個點的橫座標x,將全部的點分紅兩部分:CH(A)和CH(B),分別解決CH(A)和CH(B),而後再合併C(A)和CH(B).net
一樣的能夠按照粗暴的思路來解決,就是去看全部的兩個CH的全部頂點連線,而後看是否全部的點都在它的一側。
注意:找到兩邊都只最大的y座標來做爲一條邊會出現問題 3d![]()
以找到上邊界爲例,爲方便作一條直線使得它恰好切割兩個CH,鏈接兩個CH的點,
,這兩點據選取的軸線x之間的距離在兩個圖形中均最近。它與選定的軸交於藍線與選定實線軸交點處。code
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
選取新增的上邊接,相似的下邊界
,沿着
,按照順時針的方向,碰到邊
,
,此時的點恰好到了下邊界,而後沿着下邊界
,繼續順時針,知道
即獲得合併後的邊界
最明顯的方式就是先排序,而後就直接獲取了,排序算法的時間爲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選取很差整個的時間爲。
將S分紅5列,這樣它就是有多行數據,一共5列的二維數組,把每列進行排序,最大的元素在上頭,最後x的取值爲全部列中間取值的中間的值
方便畫有行列交換
通過這麼劃分,能夠看到
這裏取 n/10的上邊界。能夠看到一共有 n/5 行,而有一半的行都會存在小於X的數,每行都會有3個,除了包含X的那一行和不足5個元素的最後一行
能夠獲得整個的耗時爲
全部的除法所有上取整
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)。