/*
[数据流的中位数]
[题目]
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
[解析]
注意题目中的关键字“数据流”。
方法1:
可以考虑每次需要获取中位数时都在当前数组中进行查找,使用 top k 的思想最优是 O(n) 的复杂度找到,
如果查询次数多的话,那么复杂度会很高,数据不断增加,数组是乱序的。
方法2:
维持一个有序的数组,新数到来时插入到有效的位置,顺序插入复杂度是 O(n),
最优可以使用二分查找在 O(log(n)) 复杂度内找到插入的位置,但插入时需要移动数字,
复杂度还是O(n),当插入操作很多时候复杂度也会很大。
最优解:
插入时间复杂度: O(log(n/2));查询复杂:O(1)。
核心思想是将数字分成左右两个部分,并且两个部分元素的个数最多不超过1,左边部分小于等于中位数,而右边部分大于等于中位数。
左边部分使用最大堆存储,max_heap,右边部分使用最小堆存储 min_heap。
(1)当两个堆的元素个数相等时,或min_heap中元素个数较少时,将新的数插入到右边部分,
即 min_heap 中,此时如果要插入的数 num 小于堆顶,那么就说明 num 应该被放到左半部分,
这个时候需要将 num 插入到 max_heap 中,然后获取 max_heap 中当前的最大值并弹出,
这才方可将弹出的数插入到 min_heap 中。(2)当 max_heap 个数较少时,新增数加入,过程与前面描述类似。
查找时:如果 max_heap 和 min_heap 个数相等则说明数组长度为偶数,返回两个堆顶的均值即可;
否则,根据规则肯定是 min_heap 中多处一个数,这个时候返回 min_heap 的堆顶。
实现细节:
可以使用 C++ 中的 priority_queue 实现堆。也可以使用
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> // for less and greater function
using namespace std;
class Solution{
public:
void Insert(int num){
if(max_heap.size() < min_heap.size()){
// insert into max_heap
if(!max_heap.empty() && max_heap.front() < num){
min_heap.push_back(num);
push_heap(min_heap.begin(), min_heap.end(), greater<int>());
num = min_heap.front();
pop_heap(min_heap.begin(), min_heap.end(), greater<int>());
min_heap.pop_back();
}
max_heap.push_back(num);
push_heap(max_heap.begin(), max_heap.end(), less<int>());
}else{
// insert into min_heap
if(!min_heap.empty() && min_heap.front() > num){
max_heap.push_back(num);
push_heap(max_heap.begin(), max_heap.end(), less<int>());
num = max_heap.front();
pop_heap(max_heap.begin(), max_heap.end(), less<int>());
max_heap.pop_back();
}
min_heap.push_back(num);
push_heap(min_heap.begin(), min_heap.end(), greater<int>());
}
}
double GetMedian(){
if(min_heap.size() == max_heap.size() && !min_heap.empty()){
return (min_heap.front() + max_heap.front())*1.0 / 2.0;
}else{
return min_heap.front();
}
}
private:
vector<int> min_heap; // right part, value large than and equal to median
vector<int> max_heap; // left part, value less than and equal to median
// insure min_heap.size() >= max_heap.size()
// and min_heap.size() - max_heap.size() <= 1
};
int main()
{
return 0;
}
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/15282.html