剑指offer(41)
剑指offer(41)
剑指 Offer 41. 数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
- void addNum(int num) - 从数据流中添加一个整数到数据结构中。
- double findMedian() - 返回目前所有元素的中位数。
示例 1:
输入:
["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]
[[],[1],[2],[],[3],[]]
输出:[null,null,null,1.50000,null,2.00000]
示例 2:
输入:
["MedianFinder","addNum","findMedian","addNum","findMedian"]
[[],[2],[],[3],[]]
输出:[null,null,2.00000,null,2.50000]
限制:
- 最多会对
addNum、findMedian
进行50000
次调用。
利用大小顶堆来辅助进行操作,大顶堆存储小的一半,小顶堆存储大的一半
class MedianFinder {
public:
//利用小顶堆和大顶堆完成操作
priority_queue<int>bigQ;//大顶堆 堆顶是最大值
priority_queue<int,vector<int>,greater<int>>smallQ;//小顶堆 堆顶是最小值
int bigSize;//大顶堆 元素数量
int smallSize;//小顶堆元素数量
/** initialize your data structure here. */
MedianFinder() {
bigSize=0;
smallSize=0;
}
//用大小顶堆存储数据 大顶堆存较小的一半 小顶堆存较大的一半 这样中位数就可以用这两个堆顶求到
void addNum(int num) {
//如果大小顶堆数量相等 即为偶数 元素放入小顶堆
if(bigSize==smallSize){
//先放入大顶堆 防止这个数小于大顶堆的数
bigQ.push(num);
int temp=bigQ.top();
bigQ.pop();
//把大顶堆顶部元素放入小顶堆
smallQ.push(temp);
smallSize++;
}else{
//数据量为奇数 则把元素放入大顶堆
//先放入小顶堆
smallQ.push(num);
//再把小顶堆顶部元素放入大顶堆
int temp=smallQ.top();
smallQ.pop();
bigQ.push(temp);
bigSize++;
}
}
double findMedian() {
//如果元素和是奇数 则中位数应该在小顶堆顶部
if((bigSize+smallSize)%2==1)return (double)smallQ.top();
else{
//偶数则相加/2即可
return (smallQ.top()+bigQ.top())/2.0;
}
}
};
本文来自博客园,作者:{BailanZ},转载请注明原文链接:https://www.cnblogs.com/BailanZ/p/16217742.html