题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
思路:
/*
C++ 最大堆 最小堆 实现
用大顶堆实现左边的的数据容器,小顶堆实现右边的数据容器。往堆中插入一个数据时间复杂度O(logn),而得到最大值
(或最小值)只需O(1)时间。有一点需要注意,我们要保证数据被平均分配到两个堆中(想想为什么?),因此两堆大小之
差不能超过1。实现方法是数据流中奇数位的数插入小顶堆中,偶数位的数插入大顶堆中。同时还要保证大顶堆中的所有数
都要小于小顶堆中的数。考虑一种特殊情况,例如,插入偶数位的数,按照分配规则应该插入大顶堆中,但是这个数大于小
顶堆的最小值怎么办?如果直接插入大顶堆,就不符合大顶堆所有值都小于小顶堆的值这一条件。可以这样解决:想把该数
插入小顶堆,然后进行堆排序,接着讲小顶堆的最小值拿出来插入到大顶堆中,这样就满足所有条件了。同理插入奇数位的数
时也要考虑这种特殊情况。
*/
class Solution { private: vector<int> min; vector<int> max; public: void Insert(int num) { if(((min.size()+max.size())&1)==0)//偶数时 ,放入最小堆 { if(max.size()>0 && num<max[0]) { // push_heap (_First, _Last),要先在容器中加入数据,再调用push_heap () max.push_back(num);//先将元素压入容器 push_heap(max.begin(),max.end(),less<int>());//调整最大堆 num=max[0];//取出最大堆的最大值 //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据 pop_heap(max.begin(),max.end(),less<int>());//删除最大堆的最大值 max.pop_back(); //在容器中删除 } min.push_back(num);//压入最小堆 push_heap(min.begin(),min.end(),greater<int>());//调整最小堆 } else//奇数时候,放入最大堆 { if(min.size()>0 && num>min[0]) { // push_heap (_First, _Last),要先在容器中加入数据,再调用push_heap () min.push_back(num);//先压入最小堆 push_heap(min.begin(),min.end(),greater<int>());//调整最小堆 num=min[0];//得到最小堆的最小值(堆顶) //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据 pop_heap(min.begin(),min.end(),greater<int>());//删除最小堆的最大值 min.pop_back(); //在容器中删除 } max.push_back(num);//压入数字 push_heap(max.begin(),max.end(),less<int>());//调整最大堆 } } /*获取中位数*/ double GetMedian() { int size=min.size()+max.size(); if(size<=0) //没有元素,抛出异常 return 0;//throw exception("No numbers are available"); if((size&1)==0)//偶数时,去平均 return ((double)(max[0]+min[0])/2); else//奇数,去最小堆,因为最小堆数据保持和最大堆一样多,或者比最大堆多1个 return min[0]; } };
大神“马客”的代码看不懂~~~~
//设置左右两个堆
//1.保证左边的堆<=右边的堆
//2.保证两个堆大小之差能取到中位数
class Solution { priority_queue<int, vector<int>,less<int> >p; priority_queue<int, vector<int>,greater<int> >q; public: void Insert(int num) { if(p.empty() || num<=p.top()) p.push(num); else q.push(num); if(p.size()== q.size()+2) q.push(p.top()),p.pop(); if(p.size()+1==q.size()) p.push(q.top()),q.pop(); } double GetMedian() { return p.size()==q.size()?(p.top()+q.top())/2.0 : p.top(); } };