斯坦福大學算法分析與設計課--分治算法(附小姐姐視頻)

本文預計閱讀時間4分鐘,在讀的過程中你需要帶着以下問題:

  • 分治算法的基本步驟

  • 逆序對計數是如何使用分治算法來解決問題的

  • 爲什麼MergeSort排序法可以自然的算出逆序對數目

分值策略一般步驟

  1. 把輸入劃分成更小的子問題。

  2. 遞歸的治理子問題。

  3. 把子問題的解決方案組合到一起,形成原始問題的解決方案。

應用: 逆序對數目

輸入包含不同整數的數組A, 輸出A中逆序對的數量,逆序是指: 如果 i < j 而 A[i] > A[j],那麼 (i, j) 就是一組逆序對。

比如輸入的數組是

其中i = 2對應A[2] =3 ,j=4對應A[4]=2,2<4, 但是A[2] > A[4],所以這是一組逆序對。

協同篩選

爲什麼要對數組的逆序對計算?

一個原因是想要計算一種數值相似度,該數值的相似度用於對兩個已排序列表之間的相似度進行量化。比如兩個人都看過10部電影,按照從最喜歡到最不喜歡的順序進行排列,那麼怎麼衡量兩個人的選擇是相似還是不相似的呢?解決這個問題的一種量化方法就是通過包含10個元素的數組A,A1表示讀者的朋友從電影列表中選擇最喜歡的電影,a2表示他喜歡第二的電影,以此類推,a10表示他最不喜歡的電影,這樣如果讀者最喜歡的電影是星球大戰,而這部電影在讀者的列表中只顯示的第5位,那麼a1就等於5,如果兩個人的排序是相同的,這個數組就已經排序了,不存在逆序對,如果這個數組包含的逆序對越多,讀者和朋友之間對電影評價的分歧就越多,對電影的偏好就不同了。

對已排序列表進行相似性測量的另一個原因就是協同篩選,這是一種任意生成推薦方案的方法,網站就怎麼推出關於產品電影歌曲內容的建議呢?在協同篩選中,其思路就是尋找其他與它相似偏好的用戶,然後推薦他們所喜歡的內容。因此協同篩選需要用戶「相似性」的定義,而計算逆序對就可以捕捉問題的本質。

暴力解法

我們首先想到的就是暴力窮舉搜索法,輸入一個數組A,裏面包含不同的整數,輸出的是它的逆序對個數,以上就是暴力解法的僞代碼。外層循環i表示從左到右的遍歷數組A中的元素,內層循環j是沒有與i對比過的元素,逆序了就累加。它的缺點是時間複雜度很高,O(n^2)。

分而治之思想


如果我們用分治算法來算這個問題的話,第一個步驟就是把數組A劃分成更小的子問題,我們把A平均的劃分成兩個部分,左邊和右邊,這樣數組規模就變小了,這樣劃分下就有三種情況:

  • 第1種就是逆序對 i 和 j 都位於數組的左半部分,就是下標 i 和 j 是小於等於n/2的

  • 第2種情況是逆序對 i 和 j 位於數組的右半部分

  • 第3種情況是逆序對 i 位於左半部分 j 位於右半部分,以上是僞代碼。

接下來我們需要解決子問題,對於情況1,2其實就是調用自身的遞歸,所以我們只用實現第3鍾情況CountSplitInv。

MergeSort思想

在CountInv的僞代碼中,需要實現CountSplitInv函數,我們之前講的MergeSort排序算法天然的可以計算逆序對數目,而它實現的思路又是兩個已排序的數組合併成一個新數組,上面的CountInv的情況3實際就是i在左邊數組中,j在右邊數組中,而左右兩邊的數組沒有排序,所以我們對他兩排一下序就能引用MergeSort算法。我們稍微的修改一下上面的僞代碼,使得遞歸後除了返回逆序對數目,還要返回排序後的數組,下面是修改後的僞代碼。


那麼以上在處理逆序對 i, j 一個在左邊一個在右邊這種情況的時候,就可以用上之前的MergeSort算法,現在我們來回顧一下。

以上是MergSort的僞代碼,它是輸入已排序的C和D,輸出是排序好的B。i,j分別控制C,D的元素,哪個元素小就把它加入到B中。那麼,這裏的C就是原問題中的左半部,D就是原問題的右半部分,當C[i] > D[j] 的時候,說明產生了逆序對,而C又是排序後的,所以i之後的數字都是大於D[j]的,所以對於D[j]所帶來的逆序對數目就是C數組i到最後的元素個數,所以,我們可以在排序的基礎上計算出逆序對個數。把這一段話翻譯成僞代碼就是如下。

這樣就完成了分治算法對於逆序對的計算。時間複雜度是O(nlogn),比暴力搜索快很多。文章開頭的問題你想通了嗎?ps:開頭的視頻,是美女小姐姐錄製的哦,記得拉上去看看!


有熱門推薦????

釘釘被小學生組團,給好評打一星,被迫下架!

一個相當有用的利器,提高檢索匹配的效率!

爬蟲,反爬蟲,反反爬蟲,這之間的鬥爭恢宏壯闊...

5萬人遠程辦公的第一天,萬萬沒想到……