斯坦福算法設計和分析_3. 分治算法


​本文預計閱讀時間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),比暴力搜索快很多。文章開頭的問題你想通了嗎?
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM