劍指offer--隨時找到數據流的中位數

有一個遠遠不斷的吐出整數的數據流,假設你有足夠的空間來保存吐出的數,請設計一個名叫MedianHolder的結構,MedianHolder可以隨時去的之前吐出所有數的中位數。

要求:1.如果MedianHolder已經保存了吐出的N個數,那麼任意時刻將一個新數加入到MedianHolder的過程,其時間複雜度爲O(logN)。

2.取得已經吐出的N個數整體的中位數的過程,時間複雜度爲O(1)。

思路:準備兩個堆,一個大根堆,一個小根堆。力爭做到如果排完序之後,前n/2個數放在大根堆裏面,後n/2個數放在小根堆裏面。這樣大根堆的堆頂和小根堆的堆頂就一定能壓中中位數。比如7,3,4,5這樣一個數據流,就把3,4放在大根堆裏面,4在堆頂;7,5放在小根堆裏面,5在堆頂。則4和5正好是可以壓中中位數的位置。

具體做法是:一開始兩個堆都是空的,遇到的第一個數默認放在大根堆裏面,新的數記爲new_number,如果這個數小於等於大根堆的堆頂,就把new_number放到大根堆的堆頂去;如果new_number大於大根堆的堆頂,就放到小根堆裏面去。如果不平也好解決。比如如果第一個數是5,就把5放到大根堆裏面,接下來再遇到3,則3放到大根堆裏面去,這個時候大根堆有2個數,小根堆有0個數,而我們每加一個數,都考察一下兩個堆的size大小是否超過1 。當一個size是2一個size是0的時候就超過了,這個時候大根堆的堆頂彈出一個5進小根堆,就又平了。接下里再遇到一個數6,大於大根堆的堆頂3,則6直接進小根堆;接下來又來一個數4,4比3大,則4也進小根堆,這時候兩個堆size差值又超過1了,則小根堆的堆頂彈出一個4進大根堆,此時大根堆堆頂是5,小根堆堆頂是4,又壓中了中位數的位置。所以整個策略就是,只關心大根堆的堆頂,判斷當前數與大根堆堆頂的關係來決定當前數進大根堆還是小根堆。如果兩個堆的size大小超過了1,就讓較大的堆的堆頂彈出進另外一個堆。這樣一直可以保證前n/2個數放在大根堆裏面,後n/2個數放在小根堆裏面。

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