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 出來的一定是右半部分最小的數值。
?? 但他也一定是左半部分最大的數值。把它押進左半部分。 ??
如果此時左半部分個數大于了右半部分的,那么再把左半部分的最小大值,彈出來給右半部分
- 正如上面打問號的部分,這個說法是錯的。
如果剛進來的值就是最小的,那么他就會被 big 彈出來,然后插入small, small 再把他里面最大的值彈出來給big
所以這里其實有一個reheap 的過程。我一開始忽略掉了,所以有錯。
為了實現 max-heap 的效果,small 都是插入負值,這樣,優先級就會顛倒。也就是 map-heap 了。
Anyway, Good luck, Richardo! -- 09/15/2016