JZ63 数据流中的中位数**
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路
暴力解法:利用有序数组,来一个数就把它***已经拍好序的数组里,然后取中位数的时候直接取中间索引就可以
(看到剑指上有别的解法,之后可以考虑用大根堆,小根堆的方法进行)
代码
class Solution { public: vector<int> data; void Insert(int num) { data.push_back(num); int pos=data.size()-1; //确定num的位置 for(int i=0;i<data.size()-1;i++) { if(data[i]>=num) { pos=i; break; } } for(int i=data.size()-1;i>pos;i--) { data[i]=data[i-1]; } data[pos]=num; } double GetMedian() { int n=data.size(); if(n%2==1) return data[n/2]; else return (data[n/2]+data[n/2-1])/2.0; } };
方法二
采用堆的方法
一般来说,什么时候用堆,什么时候用排序呢?
如果有取数,放回,取数,放回的操作的时候,用堆更加方便(有放回的时候用堆)
这道题的策略:
- 创建一个大根堆和一个小根堆
- 第一个数放进大根堆(大根堆为空的时候放进来)
- 放的数如果小于等于大根堆的堆顶,则放进大根堆;否则,放进小根堆
- 每次放完数后,比较大小根堆的差值,差值等于2的话就进行调整(将多的那个堆的堆顶放入少的堆)
- 这样的操作会使得一半在大根堆,一半在小根堆里
取中位数:两堆大小相等,取两个堆顶的平均值;不等的话就取多的堆的堆顶
这道题明白思路之后我花了好久好久!!!
注意:这里的大根堆指的是,堆顶元素最大,在C++中,定义大根堆:priority_queue<int,vector<int>,less<int>> maxQ;</int></int>
代码
class Solution { public: priority_queue<int,vector<int>,greater<int>> minQ; priority_queue<int,vector<int>,less<int>> maxQ; void Insert(int num) { if(maxQ.empty()||num<=maxQ.top()) maxQ.push(num); else minQ.push(num); if(maxQ.si***Q.size()==2) { minQ.push(maxQ.top()); maxQ.pop(); } if(minQ.size()-maxQ.size()==2) { maxQ.push(minQ.top()); minQ.pop(); } } double GetMedian() { if(maxQ.si***Q.size()) return (maxQ.top()+minQ.top())/2.0; else if(maxQ.size()>minQ.size()) return maxQ.top(); else return minQ.top(); } };