如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數。
使用一個大頂堆max_heap維護前n/2較小的數,一個小頂堆min_heap維護後n/2的較大的數。當n爲偶數時,max_heap.size()會和min_heap.size()相等;當n爲奇數時max_heap.size()=min_heap.size()+1;
由於優先級隊列底層是堆的數據結構,使用c++中現有的priority_queue,默認版本爲大數在最前面(即默認爲大頂堆)。
以下爲代碼:
class Solution {
public:
void Insert(int num)
{
//第奇數個數放入大頂堆
if (((max_heap.size() + min_heap.size()) & 1) == 0 )
{
if (min_heap.size() > 0&& num > min_heap.top())
{
//加入的數比小頂堆堆頂元素大,加入小頂堆後,再取小頂堆堆頂元素
//始終保持小頂堆中元素比大頂堆中元素大
min_heap.push(num);
num = min_heap.top();
min_heap.pop();
}
max_heap.push(num);
}
else
{
//第偶數個數放入小頂堆
if (max_heap.size()>0&&num < max_heap.top())
{
//加入的數比大頂堆堆頂元素小,加入大頂堆後,再取大頂堆堆頂元素
max_heap.push(num);
num = max_heap.top();
max_heap.pop();
}
min_heap.push(num);
}
}
double GetMedian()
{
double result = 0;
if (max_heap.size() == min_heap.size())
{
result = (max_heap.top() + min_heap.top()) / 2.0;
}
else
{
result = max_heap.top();
}
return result;
}
private:
//小頂堆維護後n/2個較大的數
priority_queue<int, vector<int>, greater<int>> min_heap;
//小頂堆維護前n/2(或n/2+1)個較小的數
priority_queue<int, vector<int>, less<int>> max_heap;
};