一问题描述


 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或者优先队列等等,当然还得采用上述算法,否则会超时。此处不贴代码。

 

三总结


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

posted on 2015-12-30 19:19  YJBlog  阅读(272)  评论(0编辑  收藏  举报