【LeetCode & 剑指offer刷题】查找与排序题3:41 数据流中的中位数(295. Find Median from Data Stream)
【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
41 数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
/*
1 2 3 4 [5] + [6] 7 8 9 10
大顶堆 + 小顶堆
方法一:用两个堆(stl中的priority_queue)
过程:用于一个大顶堆实现左边容器,小顶堆实现右边容器,根据左边最大数与右边最小数得到中位数
(1) 平均分配
(2) 还要保证大顶堆中所有数据小于小顶堆中元素,比较新数据与大顶堆和小顶堆堆顶元素就知道该放到哪里
插入O(logn) 得到中位数O(1),空间复杂度O(n)
*/
class Solution
{
private:
priority_queue<int> maxheap; //stl中默认为大顶堆(联系默认的二叉搜索树,
//根结点较左子树大,中序遍历从小到大,不同的是大顶堆根结点较左右子树都大)
priority_queue<int, vector<int>, greater<int>> minheap; //小顶堆
public:
void Insert(int num)
{
if(maxheap.empty() || num<maxheap.top()) maxheap.push(num); //如果新数属于小的一半(左边)
else minheap.push(num);
if(maxheap.size() < minheap.size()) //保持两边长度一致(左边比右边多一或者左右两边长度一样)
{
maxheap.push(minheap.top());
minheap.pop();
}
else if(maxheap.size() > minheap.size() + 1)
{
minheap.push(maxheap.top());
maxheap.pop();
}
}
double GetMedian()
{
return (maxheap.size()>minheap.size())? maxheap.top(): (maxheap.top() + minheap.top())*0.5; //奇数时,返回中间元素,偶数时,返回中间两个数的平均数,注意浮点数的处理
}
};