【算法/劍指Offer】如何得到一個數據流中的中位數

如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用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;
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章