您的位置:首页 > 职场人生

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

2015-09-03 17:18 507 查看
题目描述:

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

解题思路:

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

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

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

用数组来存储,如果是无序数组,则插入效率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;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: