1. 程式人生 > >《演算法導論》選擇問題(找第K大的數)

《演算法導論》選擇問題(找第K大的數)

選擇問題(Selection Problem),即在n個元素的集合中尋找第K小的元素的問題。第K小的元素又叫第K個順序統計量。有以下幾種變體:
- 找最大值和最小值;同時找最大和最小值
- 找中位數(第n/2小)
- 找任意第K小的元素
- 找Top-K的元素

找最大值和最小值

要確定最大值或者最小值,在n個元素中進行n-1次比較是必須的,也是最優方法。

要同時確定最大值和最小值,如果獨立尋找,各用n-1次比較,共用2n-2次比較,但這不是最優方法。

事實上,最多需要3n/2次比較就可以同時找到最大最小值:

  1. 成對處理元素,兩兩成對比較大小,得到較大的元素和較小元素(1次比較)
  2. 較大元素和當前最大值比較,較小元素和當前最小值比較(2次比較)
  3. 處理n/2對元素共需要3n/2次比較

當n為奇數,把第一個元素設為最大值和最小值,剩下的兩兩成對,共做3n/2次比較;當n為偶數,先做一次初始比較,然後做剩下的3(n-2)/2次比較,共3n/2-2次比較。因此最多做3n/2次比較。

選擇演算法(線性時間)

類似於快排的劃分函式,用分治法實現最壞情況線性時間O(n)的選擇演算法。

選擇演算法Select(S, k):
1. 將n個元素劃分為n/5組,每組5個元素,最多有一個組由剩下的n mod 5個元素組成
2. 尋找ceil(n/5)個組中每一組的中位數:對每組5個元素進行插入排序,排序後選擇中位數
3. 從2中找出的ceil(n/5)箇中位數,遞迴呼叫Select()找出其中位數x
4. 用劃分函式將輸入元素按x進行劃分,比x小的構成S1,比x大的構成S2
5. 如果|S1|=k-1,則返回x為所求(第k小)
6. 否則如果|S1|>k,則在S1呼叫Select(S1, k);否則在S2呼叫Select(S2, k-|S1|-1)

用迭代法可以證明這個Select演算法將時間複雜度降到限行時間O(n)

Reference

  • 《演算法導論(第二版)》第9章