題目描述
如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數
Solution
使用一個小頂堆和一個大頂堆存儲數據,小頂堆所有的數都大於大頂堆,插入數據時保持兩個堆大小相差不超過1,這樣中位數會在小頂堆和大頂堆的堆頂產生
- 當前數據量爲偶數時,插入新數據時,要讓小頂堆大小加1,將新數據插入大頂堆中,將大頂堆堆頂移入小頂堆(按序插入新數據)
- 當前數據量爲奇數時,插入新數據時,要讓大頂堆大小加1,保持兩個堆大小相差不超過1,將新數據插入小頂堆中,將小頂堆堆頂移入大頂堆(按序插入新數據)
- 當前數據量爲偶數時,中位數爲兩個堆頂的平均值;當前數據量爲奇數時,中位數爲小頂堆堆頂
public class Solution {
private int count = 0;
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
public void Insert(Integer num) {
if (count % 2 == 0) {
maxHeap.offer(num);
int max = maxHeap.poll();
minHeap.offer(max);
} else {
minHeap.offer(num);
int min = minHeap.poll();
maxHeap.offer(min);
}
count++;
}
public Double GetMedian() {
if (count % 2 == 0) {
return new Double(maxHeap.peek() + minHeap.peek()) / 2;
} else {
return new Double(minHeap.peek());
}
}
}