面试题_64——数据流中的中位数

来源:互联网 发布:淘宝活动报名店铺故事 编辑:程序博客网 时间:2024/03/29 23:29
题目描述:

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。


解题思路:

数据流证明是输入数据大小是动态变化的。

我们要从动态变化的数据流中找现有数据的中位数。首先需要考虑,这些数据流中的数据该怎么存储?

即 用什么数据结构进行存储? 从而最方便查找中位数。

用数组来存储,如果是无序数组,则插入效率O(1) , 查找中位数效率O(n);

如果用有序数组来存储,那么插入O(n),查找中位数效率O(1);

如果用链表来存储,插入O(1),查找O(n);

用二叉搜索树来存储,插入平均O(logn),最差O(n),查找中位数效率平均O(logn),最差O(n);

AVL树,插入O(logn),查找中位数O(1);

最大堆 和 最小堆,插入O(logn),查找中位数O(1).


AVL树在C++STL中没有直接库函数可用,需要自行编写,实现起来比较复杂。

因此,用堆来实现本题目的需求是最佳选择。

利用C++,STL库中,push_heap()、pop_heap()、vector 以及 比较函数 less<type>() 和 greater<type>()

来实现堆得操作。


具体思路如下:

1、维护两个堆,一个小顶堆,一个大顶堆。

大顶堆max小顶堆min
max中存储当前数据流中较小的一半;

min中存储当前数据流中较大的一半;

同时,需要满足:max中的所有数据 都 小于 min中存储的所有数据。

(这里要在编程实现的时候做处理,即拿当前的数据与堆顶数据进行比较。然后,拿到符合要求的数据)

这样,数据流中的数据分为两个部分,较大的一部分、较小的一部分。

取中位数就直接取大顶堆堆顶 或 小顶堆堆顶。

当数据流中数据数目是奇数个就插入——>小顶堆;

当数据流中数据数目是偶数个就插入——>大顶堆;
那么,最后,取中位数,奇数就去小顶堆,偶数就取两个堆顶和的平均值。


实现代码:

class Solution {public:    void Insert(int num)    {        if(( (max.size() + min.size()) & 1 ) == 0)        {            if(max.size() > 0 && num < max[0])            {                max.push_back(num);                push_heap(max.begin(), max.end(), less<int>());                num = max[0];                pop_heap(max.begin(),max.end(),less<int>());                max.pop_back();            }                         min.push_back(num);            push_heap(min.begin(), min.end(), greater<int>());        }        else        {            if(min.size() > 0 && num > min[0])            {                min.push_back(num);                push_heap(min.begin(), min.end(),greater<int>());                                 num = min[0];                                 pop_heap(min.begin(),min.end(),greater<int>());                min.pop_back();            }                         max.push_back(num);            push_heap(max.begin(),max.end(),less<int>());        }                         }     double GetMedian()    {        int size = max.size() + min.size();                 if(size == 0)        {          return 0.0;          }                 double median = 0.0;        if((size & 1) == 1)        {            median = static_cast<double>(min[0]);           }        else        {            median = static_cast<double>((min[0] + max[0])/2.0);           }                 return median;    } private:    vector<int> max;    vector<int> min;};







0 0
原创粉丝点击