Find Median from Data Stream -- Leetcode

来源:互联网 发布:下架黄耀明音乐知乎 编辑:程序博客网 时间:2024/06/11 05:22

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.

For example:

add(1)add(2)findMedian() -> 1.5add(3) findMedian() -> 2

解法思路:

维持两个优先级队列。较小的数放一队列,较大的数放另一队列。

较小的用大顶堆,较大的用小顶端。  即通过顶端,取小队列中的最大值;取大队列中的最小值。


所要注意的是,下面这个写法,在加入时,要注意双向移动。

单向移动会导致,一个较小的值,移入大队列后,无法回到小队列。


具体来讲,

维持一个不变式:小队列中的数,全部小于 大队列中的数。


如果想在大队列中增加一个数,只需要首先将数压入小队列,然后将小队列中最大值,移入大队列。  即能保证上面的不变式。


如果想在小队列中增加一个数,需要做到双向移动。即,先将数压入小队列,然后,将小队列中的最大值与大队列中的最小值做交换。 方能保证上面的不变式。

                                             当然,这一步也可以按,压入大队列,将大队列的最小数移入 小队列。



class MedianFinder {    priority_queue<int> small;    priority_queue<int, vector<int>, greater<int> > large;    public:    // Adds a number into the data structure.    void addNum(int num) {        small.push(num);        large.push(small.top());        small.pop();                if (large.size() > small.size()) {            small.push(large.top());            large.pop();        }    }    // Returns the median of current data stream    double findMedian() {        if (large.size() == small.size()) {            if (small.empty())                return 0;            else                return (double(small.top()) + double(large.top())) / 2;        }        else {            return (small.size() > large.size()) ? small.top() : large.top();        }    }};// Your MedianFinder object will be instantiated and called as such:// MedianFinder mf;// mf.addNum(1);// mf.findMedian();


将上面的addNum方法写为如下,更容易懂一些。而且,运行时间也更短。


    // Adds a number into the data structure.    void addNum(int num) {        if (small.size() > large.size()) {            small.push(num);            large.push(small.top());            small.pop();        }        else {            large.push(num);            small.push(large.top());            large.pop();        }    }



0 0
原创粉丝点击