【劍指offer】面試題41. 數據流中的中位數

解題思路

參考劍指offer的思路,要劃分出中位數x,則左邊均小於x,右邊均大於x
因此通過堆,可以設置左邊爲最大堆,堆頂即是左邊的最大值,右邊設置最大堆,堆頂即是右邊的最小值;
通過兩個堆的總size,
如果爲奇數,則爲中間數字,該值我們存放在minHeap的top中
如果爲偶數,則爲中間兩個數/2.0,即minHeap.top()+maxHeap.top()/2
大家如果不明白,可以用[2,3,4]和[2,3,4,5]兩個例子來手動模擬一下添加的過程,這樣能有更清晰的認識

代碼

class MedianFinder {
public:
	/** initialize your data structure here. */
	priority_queue<int,vector<int>,less<int>> maxHeap;//大頂堆
	priority_queue<int, vector<int>, greater<int>> minHeap;//小頂堆
	MedianFinder() {

	}
	void addNum(int num) {
		int size = maxHeap.size() + minHeap.size();
		/*
		爲了保證數據平均分配到兩個堆中,因此兩個堆中數據的數目之差不能超過1
		因此可以假定總數目爲偶數時,插入最小堆,否則插入最大堆
		如果當前總數目爲偶數,插入最小堆
		*/
		if ((size&1)==0)//判斷是否爲偶數個
		{
			/*
				如果最大堆個數不爲0
				且出現num比最大堆中的top還要小,如果直接插入最小堆(放到右邊)
				是不行的,因爲沒有遵守右邊均大於左邊,因此要先插入到最大堆
				在最大堆中,取出top,再插入到最小堆
			*/
			if (maxHeap.size() > 0 && num < maxHeap.top()) {
				maxHeap.push(num);//入堆
				num = maxHeap.top();//去堆頂元素
				maxHeap.pop();//出堆
			}
			minHeap.push(num);//插入最小堆
		}
		//如果當前總數目爲奇數,插入最大堆
		else
		{
			/*
				如果最小堆個數不爲0
				且出現num比最小堆中的top還要大,如果直接插入最大堆(放到左邊)
				是不行的,因爲沒有遵守左邊均小於右邊,因此要先插入到最小堆
				在最小堆中,取出top,再插入到最小堆
			*/
			if (minHeap.size()>0&&num> minHeap.top())
			{
				minHeap.push(num);
				num = minHeap.top();
				minHeap.pop();
			}
			maxHeap.push(num);//插入最大堆
		}
	}

	double findMedian() {
		int size = minHeap.size() + maxHeap.size();
		if (size == 0) return 0;//size爲0
		if ((size&1))//判斷是否爲奇數個
		{
			return minHeap.top();
		}
		else//偶數
		{
			return (maxHeap.top() + minHeap.top()) / 2.0;
		}
	}
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章