求無序數組的中位數

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

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

簡單的想了下:
思路1)(這個方法不行,因爲面試時真正要求是不排序)

            把無序數組排好序,取出中間的元素
            時間複雜度 採用普通的比較排序法 O(N*logN)
            如果採用非比較的計數排序等方法, 時間複雜度 O(N), 空間複雜度也是O(N).

思路2) (這是我的思路,建一個n個結點的堆的時間複雜度是多少?)
          2.1)將前(n+1)/2個元素調整爲一個小頂堆,
          2.2)對後續的每一個元素,和堆頂比較,如果小於等於堆頂,丟棄之,取下一個元素。 如果大於堆頂,用該元素取代堆頂,調整堆,取下一元素。重複2.2步           
          2.3)  當遍歷完所有元素之後,堆頂即是中位數。

思路3) 熟話說,想讓算法跑的更快,用分治!
            快速排序之所以得名"快排",絕非浪得虛名!因爲快排就是一種分治排序法!
            同樣,找中位數也可以用快排分治的思想。具體如下:
            任意挑一個元素,以改元素爲支點,劃分集合爲兩部分,如果左側集合長度恰爲 (n-1)/2,那麼支點恰爲中位數。如果左側長度<(n-1)/2, 那麼中位點在右側,反之,中位數在左側。 進入相應的一側繼續尋找中位點。(金子分析,想法是簡單,實現起來很頭大吧,因爲第二次遍歷的時候,判斷的標準就不同了,左右不都是(n-1)/2,因爲第一次已經偏了,不過思路還是可以說一下的)
            這種方法很快,但是在最壞的情況下時間複雜度爲O(N^2), 不過平均時間複雜度好像是O(N)。

引申一:
查找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小的元素即使所求。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章