Find Median from Data Stream -- Leetcode

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.5
add(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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值