求無序數組中位數的方法


轉載:http://blog.csdn.net/zdl1016/article/details/4676882

中位數即是排過序后的處於數組最中間的元素。 不考慮數組長度為偶數的情況。設集合元素個數為n。

簡單的想了下:
思路1) 把無序數組排好序,取出中間的元素
            時間復雜度 采用普通的比較排序法 O(N*logN)
            如果采用非比較的計數排序等方法, 時間復雜度 O(N), 空間復雜度也是O(N).

思路2)
          2.1)將前(n+1)/2個元素調整為一個小頂堆,
          2.2)對后續的每一個元素,和堆頂比較,如果小於等於堆頂,丟棄之,取下一個元素。 如果大於堆頂,用該元素取代堆頂,調整堆,取下一元素。重復2.2步           
          2.3)  當遍歷完所有元素之后,堆頂即是中位數。

思路3) 熟話說,想讓算法跑的更快,用分治!
            快速排序之所以得名"快排",絕非浪得虛名!因為快排就是一種分治排序法!
            同樣,找中位數也可以用快排分治的思想。具體如下:
            任意挑一個元素,以改元素為支點,划分集合為兩部分,如果左側集合長度恰為 (n-1)/2,那么支點恰為中位數。如果左側長度<(n-1)/2, 那么中位點在右側,反之,中位數在左側。 進入相應的一側繼續尋找中位點。
            這種方法很快,但是在最壞的情況下時間復雜度為O(N^2), 不過平均時間復雜度好像是O(N)。

思路4) 快排的方法存在不確定性,導致其最壞和最好的時候差別很大, 那么有沒有一種確定性的方法呢? 答案是有的
            貌似算法導論里有講到. 這里我就先不深究了, 可以參考如下的文章,
            O(n)時間快速選擇
            http://www.shadowxh.com/?p=598
            以及本文的別人的評論

引申一:
查找N個元素中的第K個小的元素(來自編程珠璣)

編程珠璣給出了一個時間復雜度O(N),的解決方案。該方案改編自快速排序。
經過快排的一次划分,
   1)如果左半部份的長度>K-1,那么這個元素就肯定在左半部份了
   2)如果左半部份的長度==K-1,那么當前划分元素就是結果了。
   3)如果。。。。。。。<K-1,那么這個元素就肯定在右半部分了。
  並且,該方法可以用尾遞歸實現。效率更高。

時間復雜度分析, 由於差不多每次都是把序列划分為一半。。。假設划分的元素做了隨機優化,時間復雜度近似於
N+N/2+N/4.... = 2N*(1-2^-(logN)) 當N較大時 約等於 2N 也就是 O(N)。

看來,快速排需的用處可大着咧。。。

也用來查找可以N個元素中的前K個小的元素,前K個大的元素。。。。等等。


引申二:
查找N個元素中的第K個小的元素,假設內存受限,僅能容下K/4個元素。
分趟查找,
第一趟,用堆方法查找最小的K/4個小的元素,同時記錄剩下的N-K/4個元素到外部文件。
第二趟,用堆方法從第一趟篩選出的N-K/4個元素中查找K/4個小的元素,同時記錄剩下的N-K/2個元素到外部文件。
。。。
第四趟,用堆方法從第一趟篩選出的N-K/3個元素中查找K/4個小的元素,這是的第K/4小的元素即使所求。


免責聲明!

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



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