資料查詢之分治法

2021-10-08 21:42:42 字數 2482 閱讀 1167

1.分治法是什麼

從定性的角度來看,分治法的核心思想就是「分而治之」。利用分而治之的思想,就可以把乙個大規模、高難度的問題,分解為若干個小規模、低難度的小問題。隨後,開發者將面對多個簡單的問題,並很快地找到答案各個擊破。在把這些簡單問題解決好之後,我們通過把這些小問題的答案合併,就得到了原問題的答案。

例1:

在乙個包含 n 個元素的無序陣列中,要求按照從小到大的順序列印其 n 個元素。

假設我們採用 n 個元素之間的兩兩比較的計算方法,去得到從小到大的序列。分析如下:

因此,要想通過上述方法直接解決乙個規模較大的問題,其實是相當困難的。

基於此,分治法的核心思想就是分而治之。具體來說,它先將乙個難以直接解決的大問題,分割成一些可以直接解決的小問題。如果分割後的問題仍然無法直接解決,那麼就繼續遞迴地分割,直到每個小問題都可解。

2. 分治法的價值

例2:

在 1000 個有序數字構成的陣列 a 中,判斷某個數字 c 是否出現過。

其實,在小資料規模上,分治法沒有什麼特殊價值。只有在大資料集上,分治法的價值才能顯現出來。

例3:

假如有一張厚度為 1 公釐且足夠柔軟的紙,問將它對折多少次之後,厚度能達到地球到月球的距離?

我們回到前面講到的在陣列 a 中查詢數字 c 的例子,如果陣列 a 的大小拓展到 549,755,813,888 這個量級上,使用第二種的二分查詢方法,僅僅需要 39 次判斷,就能找到最終結果。相比暴力搜尋的方法,效能優勢高的不是一星半點!這也證明了,複雜度為 o(logn) 相比複雜度為 o(n) 的演算法,在大資料集合中效能有著爆發式的提高。

3. 分治法的使用方法

分治法在每輪遞迴上,都包含了分解問題、解決問題和合併結果這 3 個步驟。

以二分查詢為例,關於分治法在排序中的使用,我們會在第 11 課時中講到。查詢問題指的是,在乙個有序的數列中,判斷某個待查詢的數字是否出現過。二分查詢,則是利用分治法去解決查詢問題。通常二分查詢需要乙個前提,那就是輸入的數列是有序的。

二分查詢的思路比較簡單,步驟如下:

選擇乙個標誌 i 將集合 l 分為二個子集合,一般可以使用中位數;

判斷標誌 l(i) 是否能與要查詢的值 des 相等,相等則直接返回結果;

如果不相等,需要判斷 l(i) 與 des 的大小;

基於判斷的結果決定下步是向左查詢還是向右查詢。如果向某個方向查詢的空間為 0,則返回結果未查到;

回到步驟 1。

我們對二分查詢的複雜度進行分析。二分查詢的最差情況是,不斷查詢到最後 1 個數字才完成判斷。那麼此時需要的最大的複雜度就是o(logn)

例4:

下面我們一起來看乙個例子。在陣列 中,查詢 8 是否出現過。

首先判斷 8 和中位數 5 的大小關係。因為 8 更大,所以在更小的範圍 6, 7, 8, 9, 10 中繼續查詢。此時更小的範圍的中位數是 8。由於 8 等於中位數 8,所以查詢到並列印查詢到的 8 對應在陣列中的 index 值。

從**實現的角度來看,我們可以採用兩個索引 low 和 high,確定查詢範圍。最初 low 為 0,high 為陣列長度減 1。在乙個迴圈體內,判斷 low 到 high 的中位數與目標變數 targetnumb 的大小關係。根據結果確定向左走(high = middle - 1)或者向右走(low = middle + 1),來調整 low 和 high 的值。直到 low 反而比 high 更大時,說明查詢不到並跳出迴圈。我們給出**如下:

public

static

void

main

(string[

] args)

;int middle =0;

int low =0;

int high = arr.length -1;

int isfind =0;

while

(low <= high)

else

if(arr[middle]

> targetnumb)

else}if

(isfind ==0)

}

我們基於這個例子,可以對它進行一些經驗和規律的總結:

二分查詢的時間複雜度是 o(logn),這也是分治法普遍具備的特性。當你面對某個**題,而且約束了時間複雜度是 o(logn) 或者是

o(nlogn) 時,可以想一下分治法是否可行。

二分查詢的迴圈次數並不確定。一般是達到某個條件就跳出迴圈。因此,編碼的時候,多數會採用 while 迴圈加 break 跳出的**結構。

二分查詢處理的原問題必須是有序的。因此,當你在乙個有序資料環境中處理問題時,可以考慮分治法。相反,如果原問題中的資料並不是有序的,則使用分治法的可能性就會很低了。

凸包問題之分治法

凸包 按橫座標排序,以最小點與最大點之間的連線為準,在直線一側找使三角形面積最大的點,此點必在凸包內,以找到點與最大點或最小點繼續遞迴以尋找最大三角形面積尋找凸包點,直至找不到符合條件的點。實現 如下 include include include define max size 10001 str...

演算法之分治法練習題

一.單選題 共6題,100.0分 1二分查詢的時間複雜度是 a o nlogn b o n c o logn 2 d o logn 正確答案 d 我的答案 d 得分 16.6分 2實現快速排序演算法如下 private static void quicksort int p,int r if pa ...

最大子段和之分治法

問題描述 給定乙個陣列,找出其中可以構成最大數的子段,需要注意的是,這個不同於最大子串行求和 最大字段求和 字段必須是連續的 最大子串行求和 子串行只要是包含在原來的序列中即可 舉個例子 1 4 3 1 5 1 4 5 2 求上述的陣列中的最大欄位和,不難得知,最大子段和就是 10 也就是子段4 3...