leetcode No295. Find Median from Data Stream

Question

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

Algorithm:

数据结构addNum复杂度findMedian复杂度
无序数组O(1)O(n)
有序数组O(n)O(1)
有序链表O(n)O(1)
二叉搜索树平均O(logn),最差O(n)平均O(logn),最差O(n)
AVL树O(logn)O(logn)
最大堆和最小堆O(logn)O(logn)

综上,由于大部分函数库都没有AVL这个数据结构,实现起来很复杂。
所以我们使用最大堆和最小堆来解决。
我们可以把数据分成2部分,位于容器左边部分的数据比右边的数据小。我们只要得到左边部分最大的数P1,和右边部分最小的数P2。
用最大堆实现左边的容器,最小堆实现右边的容器。

首先要保证数据平均分配到两个堆中,因此两个堆中数据数目之差不能超过1。
还要保证最大堆中里的所有数据都要小于最小堆中的数据。

addNum步骤:
1、如果要插入的数据小于左边的最大值,或者左边为空,插到左边,否则插入到右边
2、如果左-右数据之差超过1,把左边的顶端值,插入到右边
3、如果右-左数据之差超过1,把右边的顶端值,插到左边
findMedian步骤:
1、左边数据相等,两个顶端值求平均
2、左>右,左的顶端值
3、左<右,右的顶端值
由于,在C++中,优先队列priority_queue是以heap完成,所以我们用优先队列解决问题。

Code

class MedianFinder {
public:
    priority_queue<int,vector<int>,greater<int> > min_heap;
    priority_queue<int,vector<int>,less<int> > max_heap;
    // Adds a number into the data structure.
    void addNum(int num) {
        if(max_heap.empty())
            max_heap.push(num);
        else if(num<max_heap.top()){
            max_heap.push(num);
            if(max_heap.size()-min_heap.size()>1){
                min_heap.push(max_heap.top());
                max_heap.pop();
            }
        }
        else{
            min_heap.push(num);
            if(min_heap.size()-max_heap.size()>1){
                max_heap.push(min_heap.top());
                min_heap.pop();
            }
        }
    }
    // Returns the median of current data stream
    double findMedian() {
        if(max_heap.size()==min_heap.size())
            return (max_heap.top()+min_heap.top())/2.0;
        else if(max_heap.size()>min_heap.size())    
            return max_heap.top();
        else
            return min_heap.top();
    }
};

// Your MedianFinder object will be instantiated and called as such:
// MedianFinder mf;
// mf.addNum(1);
// mf.findMedian();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值