leetcode 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.
For example:

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

用一个最大堆存放比中位数小(或等于)的元素,用一个最小堆存放比中位数大(或等于)的元素。这里关键的方法是insert(),每当要插入一个元素时,根据判断条件将它插入最大堆或是最小堆,并更新最大堆和最小堆,使得最大堆和最小堆中元素的个数之差不超过1,这样中位数就是最大堆或最小堆的堆顶元素。当最大堆和最小堆中元素个数不同(个数相差为1)时,元素个数多的那个堆的堆顶元素即为中位数;如果两者元素个数相同,那么中位数可以是最大堆和最小堆的堆顶元素的值取平均。

建议和这一道题leetcode 480. Sliding Window Median 滑动窗口中位数 一起学习

代码如下:

import java.util.Collections;
import java.util.PriorityQueue;

/*
 * 用一个最大堆存放比中位数小(或等于)的元素,用一个最小堆存放比中位数大(或等于)的元素。
 * 这里关键的方法是insert(),每当要插入一个元素时,根据判断条件将它插入最大堆或是最小堆,
 * 并更新最大堆和最小堆,使得最大堆和最小堆中元素的个数之差不超过1,这样中位数就是最大堆
 * 或最小堆的堆顶元素。当最大堆和最小堆中元素个数不同(个数相差为1)时,
 * 元素个数多的那个堆的堆顶元素即为中位数;如果两者元素个数相同,那么中位数可以是最大堆和
 * 最小堆的堆顶元素的值取平均
 * */
class MedianFinder 
{
    private PriorityQueue<Integer> maxHeap;
    private PriorityQueue<Integer> minHeap;

    public MedianFinder() 
    {
        this.minHeap = new PriorityQueue<Integer>();
        this.maxHeap = new PriorityQueue<Integer>(Collections.reverseOrder());
    }

    // Adds a number into the data structure.
    public void addNum(int num) 
    {
        maxHeap.add(num);              
        minHeap.add(maxHeap.poll());             
        if(maxHeap.size() < minHeap.size())
        {
            maxHeap.add(minHeap.poll());       
        }
    }

    // Returns the median of current data stream
    public double findMedian() 
    {                    
        if(maxHeap.size() == minHeap.size())
            return (maxHeap.peek() + minHeap.peek()) / 2.0;
        else
            return maxHeap.peek();  
    }
};

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

下面是C++的做法,就是维护两个堆来实现中位数的查找

代码如下:

#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>

using namespace std;

class MedianFinder 
{
    priority_queue<long> small, large;
public:

    void addNum(int num) 
    {
        small.push(num);
        large.push(-small.top());
        small.pop();
        if (small.size() < large.size()) 
        {
            small.push(-large.top());
            large.pop();
        }
    }

    double findMedian() 
    {
        return small.size() > large.size()
            ? small.top()
            : (small.top() - large.top()) / 2.0;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值