题目详情
数据流的中位数
有一个源源不断的吐出整数的数据流,假设你有足够的空间来保存吐出的数。请设计一个名叫MedianHolder的结构,MedianHolder可以随时取得之前吐出所有数的中位数。
[要求]
- 如果MedianHolder已经保存了吐出的N个数,那么将一个新数加入到MedianHolder的过程,其时间复杂度是O(logN)。
- 取得已经吐出的N个数整体的中位数的过程,时间复杂度为O(1)
每行有一个整数opt表示操作类型
若opt=1,则接下来有一个整数N表示将N加入到结构中。
若opt=2,则表示询问当前所有数的中位数
示例1
输入
复制
[[1,5],[2],[1,3],[2],[1,6],[2],[1,7],[2]]
返回值
复制
[5,4,5,5.5]
说明
第一次查询时结构内的数为:5
第二次查询时结构内的数为:3 5
第二次查询时结构内的数为:3 5 6
第二次查询时结构内的数为:3 5 6 7
示例2
输入
复制
[[2],[1,1],[2]]
返回值
复制
[-1,1]
分析
- 题目要求复杂度为
log(n)
,且整个过程是个动态(不断插入元素)的过程,可想而知只有二叉树之类的方法可以达到这个复杂度。 - 中位数即某个能将所有数根据大小关系划分为左右两半的数,只要能够不断的维护好这两部分的数,中位数就能在
O(1)
的时间内求得- 如果
n % 2 == 0
即偶数个元素, 则median = max(left) + min(right) / 2
- 否则
n % 2 == 1
即奇数个元素,则median = max(left) or min(right)
- 如果
方法1 堆
- 使用两个堆来分别维护
left
和right
。当插入一个数的时候,朴素的想法是分别与max(left)和min(right)进行比较,之后插入到对应的堆中,再平衡两个堆的大小。但这种方法需要多个if/else
,一种优雅的方法是让数据在两个堆中流动一遍。
class Solution {
public:
/**
* the medians
* @param operations int整型vector<vector<>> ops
* @return double浮点型vector
*/
priority_queue<int, vector<int>, less<int>> lo;
priority_queue<int, vector<int>, greater<int>> hi;
vector<double> flowmedian(vector<vector<int> >& operations) {
vector