本文參考自《劍指offer》一書,代碼採用Java語言。html
更多:《劍指Offer》Java實現合集 java
如何獲得一個數據流中的中位數?若是從數據流中讀出奇數個數值,那麼中位數就是全部數值排序以後位於中間的數值。若是從數據流中讀出偶數個數值,那麼中位數就是全部數值排序以後中間兩個數的平均值。ide
所謂數據流,就是不會一次性讀入全部數據,只能一個一個讀取,每一步都要求能計算中位數。函數
將讀入的數據分爲兩部分,一部分數字小,另外一部分大。小的一部分採用大頂堆存放,大的一部分採用小頂堆存放。當總個數爲偶數時,使兩個堆的數目相同,則中位數=大頂堆的最大數字與小頂堆的最小數字的平均值;而總個數爲奇數時,使小頂堆的個數比大頂堆多一,則中位數=小頂堆的最小數字。post
所以,插入的步驟以下:測試
1.若已讀取的個數爲偶數(包括0)時,兩個堆的數目已經相同,將新讀取的數插入到小頂堆中,從而實現小頂堆的個數多一。可是,若是新讀取的數字比大頂堆中最大的數字還小,就不能直接插入到小頂堆中了 ,此時必須將新數字插入到大頂堆中,而將大頂堆中的最大數字插入到小頂堆中,從而實現小頂堆的個數多一。url
2若已讀取的個數爲奇數時,小頂堆的個數多一,因此要將新讀取數字插入到大頂堆中,此時方法與上面相似。spa
測試算例 htm
1.功能測試(讀入奇/偶數個數字)blog
2.邊界值測試(讀入0個、1個、2個數字)
//題目:如何獲得一個數據流中的中位數?若是從數據流中讀出奇數個數值,那麼 //中位數就是全部數值排序以後位於中間的數值。若是從數據流中讀出偶數個數值, //那麼中位數就是全部數值排序以後中間兩個數的平均值。 import java.util.PriorityQueue; import java.util.Comparator; public class StreamMedian { PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小頂堆,默認容量爲11 PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大頂堆,容量11 public int compare(Integer i1,Integer i2){ return i2-i1; } }); public void Insert(Integer num) { if(((minHeap.size()+maxHeap.size())&1)==0){//偶數時,下個數字加入小頂堆 if(!maxHeap.isEmpty() && maxHeap.peek()>num){ maxHeap.offer(num); num=maxHeap.poll(); } minHeap.offer(num); }else{//奇數時,下一個數字放入大頂堆 if(!minHeap.isEmpty() && minHeap.peek()<num){ minHeap.offer(num); num=minHeap.poll(); } maxHeap.offer(num); } } public Double GetMedian() { if((minHeap.size()+maxHeap.size())==0) throw new RuntimeException(); double median; if((minHeap.size()+maxHeap.size()&1)==0){ median=(maxHeap.peek()+minHeap.peek())/2.0; }else{ median=minHeap.peek(); } return median; } }
1.最大最小堆能夠用PriorityQueue實現,PriorityQueue默認是一個小頂堆,經過傳入自定義的Comparator函數能夠實現大頂堆:
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大頂堆,容量11 @Override public int compare(Integer i1,Integer i2){ return i2-i1; //降序排列 } });
PriorityQueue的經常使用方法有:poll(),offer(Object),size(),peek()等。
2.平均值應該定義爲double,且(a+b)/2.0 。
3.往最大堆中插入數據時間複雜度是O(logn),獲取最大數的時間複雜度是O(1)。
4.這道題關鍵在於分紅兩個平均分配的部分,奇偶時分別插入到最大最小堆中,利用最大最小堆性質的插入方法要掌握。