zoukankan      html  css  js  c++  java
  • Find Median from Data Stream

    一问题描述


     Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

    Design a data structure that supports the following two operations:

    • void addNum(int num) - Add a integer number from the data stream to the data structure.
    • double findMedian() - Return the median of all elements so far.

    其实就是设计两个函数,一个是不断的加入数据,一个则用来输出中位数。

    二解决思路


     这两个函数实现并不难,可以看出,这道题的难点就是完成时间问题。所以简单的直接加入,然后将所有数据再重新排序,最后输出中位数的做法很可能是通不过的。做法其实也有很多:

    1.直接从排序上下功夫。用插入排序,从最后一个元素开始找插入点的同时将元素不断的移动,比如代码:

    #define MAX 100000
    class MedianFinder {
    public:
        vector<int> m_ve;
        int m_len;
        
        MedianFinder():m_len(0), m_ve(MAX, 0){};
        
        // Adds a number into the data structure.
        void addNum(int num) {
            int index = m_len;
            while(index > 0 && num < m_ve[index - 1])
            {
                m_ve[index] = m_ve[index - 1];
                index--;
            }
            
            m_ve[index] = num;
            m_len++;
        }

        // Returns the median of current data stream
        double findMedian() {
            return ((m_len % 2)? m_ve[m_len / 2]: (m_ve[m_len / 2] + m_ve[(m_len / 2 - 1)]) / 2.0);
        }
    };

    2.改进算法。维持两个堆,大数堆是最小堆,存放比中位数大的数字,小数堆是最大堆,存放比中位数小的数字,这样做维持了两个堆size差不大于一,故而中位数只能是堆顶或者两个堆顶元素的平均值。

    代码示例:

    class MedianFinder {
    public:
        // Adds a number into the data structure.
        void addNum(int num) {
            maxH.push(num);
            int t = maxH.top();
            maxH.pop(); minH.push(t);
            int m = maxH.size(), n = minH.size();
            if (n > m) {
                int t = minH.top();
                minH.pop();

                maxH.push(t);
            }
        }

        // Returns the median of current data stream
        double findMedian() {
            int m = maxH.size(), n = minH.size();
            if (!m && !n) return 0.0;
            if (m == n) return (maxH.top() + minH.top()) / 2.0;
            return (m > n) ? maxH.top() : minH.top();
        }
    private:
        priority_queue<int, vector<int>, less<int>> maxH;      
        priority_queue<int, vector<int>, greater<int>> minH;   
    };

    3.采用适当的STL结构(能够在插入的同时自动排序,且不舍弃相同的元素)。multi_set或者优先队列等等,当然还得采用上述算法,否则会超时。此处不贴代码。

    三总结


      由此题不同解法比较,不难看出不同方法其结果的差异还是比较大的,故而为适应不同的要求,也为更好的提高自己的编程能力,对数据结构及算法的掌握能力是必不可少的。

  • 相关阅读:
    docker快速部署DNS,实现快速上线
    图解CentOS系统启动流程
    MySQL/MariaDB读写分离配置
    分享使用PHP开发留言板
    LNMP+Redis架构部署
    Mysql/Mariadb主从复制
    记一次Ubuntu19无法安装docker源
    Tomcat部署项目的三个方法
    Ubuntu部署Tomcat Web服务
    Linux简单检查服务运行脚本
  • 原文地址:https://www.cnblogs.com/YJthua-china/p/5089827.html
Copyright © 2011-2022 走看看