Leetcode - Find Median from Data Stream

My code:

public class MedianFinder {
    PriorityQueue<Integer> big = new PriorityQueue<Integer>();
    PriorityQueue<Integer> small = new PriorityQueue<Integer>();
    // Adds a number into the data structure.
    public void addNum(int num) {
        big.offer(num);
        small.offer(-1 * big.poll());
        if (small.size() > big.size()) {
            big.offer(-1 * small.poll());
        }
    }

    // Returns the median of current data stream
    public double findMedian() {
        if (big.size() > small.size()) {
            return big.peek() * 1.0;
        }
        else {
            return (big.peek() - small.peek()) / 2.0;
        }
    }
};

// Your MedianFinder object will be instantiated and called as such:
// MedianFinder mf = new MedianFinder();
// mf.addNum(1);
// mf.findMedian();

this solution is so cool.
自己沒能寫出來,看了答案,理解了,再寫,還是錯。然后才終于理解了原答案中一些我覺得完全必要的步驟,其實完全是有必要的。

reference:
https://discuss.leetcode.com/topic/27521/short-simple-java-c-python-o-log-n-o-1

他其實就是維護兩個堆,一個是 Min-heap, 一個是 max-heap

然后 min-heap 放整個數據流右半部分的數據,即,較大的數據那部分。
max-heap 放整個數據流左半部分的數據,即,較小的數據那部分。

然后, top of max-heap and top of min-heap 正好是中間的值。
如果個數是奇數,那就是 top of min-heap 是 median
如果個數是偶數,那就是 (top of min-heap + top of max-heap) / 2

然后他用了兩個技巧來實現這么兩個堆。
1.每次先往最小堆加入元素。
然后 Poll 出來,這時候poll 出來的一定是右半部分最小的數值。

?? 但他也一定是左半部分最大的數值。把它押進左半部分。 ??
如果此時左半部分個數大于了右半部分的,那么再把左半部分的最小大值,彈出來給右半部分

  1. 正如上面打問號的部分,這個說法是錯的。
    如果剛進來的值就是最小的,那么他就會被 big 彈出來,然后插入small, small 再把他里面最大的值彈出來給big
    所以這里其實有一個reheap 的過程。我一開始忽略掉了,所以有錯。

為了實現 max-heap 的效果,small 都是插入負值,這樣,優先級就會顛倒。也就是 map-heap 了。

Anyway, Good luck, Richardo! -- 09/15/2016

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容