面试题41:数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
利用大顶堆小顶堆的思想(具体参考书)
class Solution { public: vector<int> maxHeap;//最大堆,存储的是左边部分值,总体小于右边部分,最大值位于堆顶 vector<int> minHeap;//最小堆,存储的是右边部分值,总体大于右边部分,最小值位于堆顶 void Insert(int num) { if (((minHeap.size() + maxHeap.size()) & 0x1) == 0) { /* 当数据总数为偶数时,计划将要插入的数放入最小堆中。(奇数则分配到大顶堆,这样保持两边分配均匀,任何时候相差不超过1. 为了保证最小堆整体大于最大堆。 if num<大顶堆的最大值(maxHeap[0]) 则将num插入大顶堆,此时大顶堆多了一个元素; 则把大顶堆的最大值删掉,插入最小堆中。 else: 插入到最小堆中。 */ if (maxHeap.size() > 0 && num < maxHeap[0]) { //添加num到大顶堆 maxHeap.push_back(num); push_heap(maxHeap.begin(), maxHeap.end(),less<int>());//仿函数less保证插入后仍为大顶堆 //将大顶堆的堆顶元素删除并插入到小顶堆中 num = maxHeap[0]; pop_heap(maxHeap.begin(), maxHeap.end(),less<int>()); maxHeap.pop_back(); minHeap.push_back(num); push_heap(minHeap.begin(), minHeap.end(),greater<int>());//仿函数greater保证插入后仍为小顶堆 } else { //正常插入到小顶堆 minHeap.push_back(num); push_heap(minHeap.begin(), minHeap.end(),greater<int>()); } } else { /* 当数据总数为奇数时,计划将要插入的数放入最大堆中。 为了保证最小堆整体大于最大堆。 if num>小顶堆的最小值(minHeap[0]) 则将num插入小顶堆,此时小顶堆多了一个元素; 则把小顶堆的最小值删掉,插入最大堆中。 else: 插入到最大堆中。 */ if (minHeap.size() > 0 && num > minHeap[0]) { minHeap.push_back(num); push_heap(minHeap.begin(), minHeap.end(),greater<int>()); num = minHeap[0]; pop_heap(minHeap.begin(), minHeap.end(),greater<int>()); minHeap.pop_back(); maxHeap.push_back(num); push_heap(maxHeap.begin(), maxHeap.end(), less<int>()); } else { //正常插入到大顶堆 maxHeap.push_back(num); push_heap(maxHeap.begin(), maxHeap.end(), less<int>()); } } } double GetMedian() { double midNum=0; int totalSi***Heap.size() + maxHeap.size(); if (totalSize == 0) return 0; //若总数为偶数时,中位数为大顶堆堆顶+小顶堆堆顶的一半; //若总数为奇数时,中位数为小顶堆的堆顶值。(因为在插入的时候总数为偶数插入小顶堆,所以小顶堆为较多的一方) if ((totalSize & 0x1) == 0) midNum = (minHeap[0] + maxHeap[0]) / 2.0; else midNum = minHeap[0]; return midNum; } };
这里注意几点的是:
1. 在利用push_heap或pop_heap添加或删除堆元素之前,要保证已经是一个堆了。 2. 大顶堆以及升序的例子,sort_heap或sort第三个参数为less<int>(); 小顶堆以及降序的例子,sort_heap或sort第三个参数为greater<int>();头文件为#include<functional>