1. 程式人生 > >分治演算法定理、平面最近點問題

分治演算法定理、平面最近點問題

分:遞迴解決較小的問題

治:從子問題構建原問題的解

分治演算法的時間:

定理1:方程T(N)=aT(N/b)+\Theta (N^k)的解是:

O(N^{log_{b}^{a}}),a>b^{k}

O(N^{k}logN),a=b^{k}

O(N^{k}),a< b^{k}

證明用疊縮求和法

定理2:方程T(N)=aT(N/b)+\Theta (N^{k}log^{p}N)的解是

O(N^{log_{b}^{a}}),a> b^{k}

O(N^{k}log^{p+1}N),a=b^{k}

O(N^{k}log^{p}N),a<b^{k}

定理3:若\sum_{i=1}^{k}a_{i}<1,則方程T(N)=\sum_{i=1}^{k}T(a_{i}N)+O(N)的解是T(N)=O(N)

證明:使用數學歸納法,這個方程的意義是,若將原問題分解成若干不到原問題100%的若干個子問題加上合併子問題的線性時間,那麼演算法時間是O(N)

最近點問題:輸入平面上的點列P,若p_{1}=(x_{1},y_{1})p_{2}=(x_{2},y_{2}),那麼兩點之間的歐幾里得距離是[(x_{1}-x_{2})^2+(y_{1}-y_{2})^2]^{1/2},找出一對最近的點

一種顯然的方法是遍歷所有點對距離,時間是O(N^2)

若先對x座標排序,那麼花費時間是O(NlogN),對於要證明總時間是O(NlogN),不增加時間界

分解問題如下:在二位座標系中畫一條想象的垂線P,將所有點按照x座標分成左右兩個部分P_{L}P_{R},那麼距離最近的點對要麼在左邊,要麼在右邊,要麼一個在左邊一個在右邊,這就是一個典型的分治問題,由於想要O(NlogN)解,因此只能用線性附加時間計算橫跨左右的這種距離。

\delta =min(d_{L},d_{R}),若d_{c}\delta有改進,那麼一定在P左右的\delta的帶狀區域中,這就減少了需要考慮的橫跨左右的點,平均在帶狀區域中的點的數量是O(\sqrt{N}),因為想象N個點落在一個單位格子中,那麼最均勻的分佈是,長和寬都是\sqrt{N}個點,從而讓兩點之間最小值的最大值為O(\frac{1}{\sqrt{N}}),這就是帶狀區域的寬,其中的點數量就是\sqrt{N}*\frac{1}{\sqrt{N}},即O(\sqrt{N}),因此可以用O(N)時間進行蠻力計算,程式碼如下:

for (i = 0; i < N; i++)
	for (j = i + 1; j < NumPointsInStrip; i++)
		if (Dist(Pi, Pj) < ans)
			ans = Dist(Pi, Pj);

在最壞的情況下,可能所有點都在帶狀區域中,就不能保證O(N)

時間了,可以改進到最壞O(N)時間,方法是對y座標排序,程式碼如下:

for (i = 0; i < NumPointsInStrip; i++)
	for (j = i + 1; j < NumPointsInStrip; j++)
		if (Pj and Pi's coordinates differ by more than ans)
			break;
		else if (Dist(Pi, Pj) < ans)
			ans = Dist(Pi, Pj);

內層迴圈只有常數個節點需要被考慮,因此是線性時間