[leetcode][C++]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.

For example:
add(1)
add(2)
findMedian() -> 1.5
add(3) 
findMedian() -> 2


题目大意:

设计一个类的add和findMedian两个接口,使得接口add可以将整型数num加到已有序列中而接口findMedian返回已有序列的中位数。

解题思路:

最直接的思路是,每次add之后对原序列排序,但每次add都对原序列排序的方法非常之不高效,结果会超时。高效的结题思路是使用两个堆(max_heap和min_heap),分别维护原序列的前半部分数据和后半部分数据(即max_heap的元素不大于min_heap中的元素),且我们要使得这两个堆的大小之差不能超过1。下面的问题就是使用什么数据结构模拟堆和如何维护这两个堆,C++的stl里面并没有堆的模板,所以我们使用优先队列(priority_queue)来模拟堆,读者可以自行百度priority_queue的用法。priority_queue默认的是大顶堆,我们可以通过参数来创建一个小顶堆。还剩一个问题是如何维护这两个堆,使得max_heap(原序列前一半数据)里的数据不大于min_heap(原序列后一半数据)里的数据,且它俩长度之差不超过1。这里介绍两种方法,第一种方法是,当来到一个新数据时,只有三种情况:比max_heap的堆顶元素小;比min_heap的堆顶元素大;在两者之间。对应的操作是:先把新数据加到max_heap里面,如果两个堆的长度之差超过1,将删除max_heap的堆顶元素并将堆顶元素加入到min_heap中;第二种情况的操作类似第一种;第三章情况的操作是将新元素加入到max_heap和min_heap较小的一个堆里面去。第一种方法便于理解但实现麻烦。第二种方法实现比较简单,思路是这样的,新数据到达时我们直接加入到max_heap中,再取出max_heap的堆顶元素加入min_heap中,最后判断min_heap的大小是否比max_heap中的大,如果大,就把min_heap的堆顶元素放回max_heap中。这种方法可以保证两个堆的长度大小不超过1且max_heap中的元素不大于min_heap,读者可自行证明。

AC代码

class MedianFinder {
public:

    // Adds a number into the data structure.
    void addNum(int num) {
        max_pq.push(num);
        int t=max_pq.top();
        max_pq.pop();
        min_pq.push(t);
        if(min_pq.size()>max_pq.size())
        {
            int t=min_pq.top();
            min_pq.pop();
            max_pq.push(t);
        }
    }

    // Returns the median of current data stream
    double findMedian() {
        if(max_pq.size()==0&&min_pq.size()==0)
            return 0;
        return max_pq.size()>min_pq.size()?max_pq.top():0.5*(max_pq.top()+min_pq.top());
        }
        
private:
priority_queue<int,vector<int>,less<int>> max_pq;//max_heap
priority_queue<int,vector<int>,greater<int>> min_pq;//min_heap
};

// Your MedianFinder object will be instantiated and called as such:
// MedianFinder mf;
// mf.addNum(1);
// mf.findMedian();


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值