解题报告:295. 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.

Examples: 

[2,3,4] , the median is 3

[2,3], the median is (2 + 3) / 2 = 2.5

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.

题目分析:

题目说的很清楚,需要设计一个数据结构,实现插入以及寻找中位数的功能。感觉还是蛮简单的,于是很快写了用vector写了一个。结果OJ显示超时了,看了一下超时的样例,太变态了,一直在插入,寻找......超时原因就是,频繁的插入,使得vector一直在重新分配内存,而且多次全部进行排序成本太高。

 1 class MedianFinder {
 2 public:
 3     std::vector<int> m_num;
 4     // Adds a number into the data structure.
 5     void addNum(int num) {
 6         m_num.push_back(num);
 7     }
 8 
 9     // Returns the median of current data stream
10     double findMedian() {
11         sort(m_num.begin(),m_num.end());
12         int n = m_num.size();
13         return (m_num[n/2] + m_num[(n-1)/2])/2;
14     }
15 };
16 
17 // Your MedianFinder object will be instantiated and called as such:
18 // MedianFinder mf;
19 // mf.addNum(1);
20 // mf.findMedian();
View Code

考虑使用其他的数据结构。尝试一下STL中自带可排序的数据结构set,set中不能出现重复元素,考虑使用multi_set。而且题目中只关心中间的两个数,可以用两个multiset分别存放较小的部分和较大的部分,只要保证两边的容量保持平衡即可。提交之后,可以AC。除了set之外还可以考虑使用,优先队列,只要可以进行排序的stl容器都可以成功实现这个功能。

class MedianFinder {
public:
    std::multiset<int> m_left;
    std::multiset<int> m_right;
    // Adds a number into the data structure.
    void addNum(int num) {
        if (m_left.size() == m_right.size())         //判断两边容量大小
        {
            if (m_right.size()&&num > *m_right.begin())     //如果右边不为空,且新插入的值比右边最小值大,进行调整
            {                                               //将右边的最小值放入左边,新值插入右边
                m_right.insert(num);
                int temp = *m_right.begin();
                m_left.insert(temp);
                m_right.erase(m_right.begin());
            }
            else 
                m_left.insert(num);
        }
        else                                       
        {
            if (num < *m_left.rbegin())                      //同样进行判断,如果比左边最大值小,插入左边,进行调整
            {
                m_left.insert(num);
                int temp = *m_left.rbegin();
                m_right.insert(temp);
                m_left.erase(--m_left.end());
            }
            else 
                m_right.insert(num);
        }  
    }

    // Returns the median of current data stream
    double findMedian() {
        return m_left.size()==m_right.size()?(*m_left.rbegin() + *m_right.begin())/(double)2:*m_left.rbegin(); 
    }
};
View Code
原文地址:https://www.cnblogs.com/Jueis-lishuang/p/5071778.html