1. 程式人生 > 實用技巧 >劍指Offer41.資料流中的中位數

劍指Offer41.資料流中的中位數

題目連結:劍指 Offer 41. 資料流中的中位數

思路:極大堆、極小堆。因為輸入是資料流不是陣列,說明輸入的資料是不確定的。一般來說先排序,然後返回中間數,但每查詢一次就要排序,時間複雜度較高。所以想能不能每次查詢都可以直接獲取到中間數,而不是對輸入的資料排序取中間數。那麼,我們就把輸入的資料分為兩堆,每次輸入資料都只會進入兩個堆中的一個,而兩個堆的中間分界線就是中位數。

程式碼:

class MedianFinder {
    PriorityQueue<Integer> maxHeap, minHeap;

    /** initialize your data structure here. 
*/ public MedianFinder() { maxHeap = new PriorityQueue<>((a, b) -> b - a); minHeap = new PriorityQueue<>((a, b) -> a - b); } public void addNum(int num) { if(maxHeap.isEmpty()){ maxHeap.offer(num); return ; }
if(num <= maxHeap.peek()){ maxHeap.offer(num); }else{ minHeap.offer(num); } this.adjust(); } public double findMedian() { return maxHeap.size()==minHeap.size()?(double)(maxHeap.peek()+minHeap.peek())/2:maxHeap.size() > minHeap.size()?maxHeap.peek():minHeap.peek(); }
private void adjust(){ if(maxHeap.size() - minHeap.size() < 2 && maxHeap.size() - minHeap.size() > -2){ return ; } if(maxHeap.size() - minHeap.size() >= 2){ minHeap.offer(maxHeap.poll()); } if(maxHeap.size() - minHeap.size() <= -2){ maxHeap.offer(minHeap.poll()); } } } /** * Your MedianFinder object will be instantiated and called as such: * MedianFinder obj = new MedianFinder(); * obj.addNum(num); * double param_2 = obj.findMedian(); */
執行用時:75 ms, 在所有Java提交中擊敗了92.29%的使用者 記憶體消耗:49.8 MB, 在所有Java提交中擊敗了40.09%的使用者