【剑指offer】面试题41. 数据流中的中位数

2020.7.17更新

左中位数,大顶堆
右中位数,小顶堆
当奇数个数时,中位数是大顶堆中的top
当偶数个数时,中位数是大顶堆的top+小顶堆的top 的平均

class MedianFinder {
public:
    /** initialize your data structure here. */
    std::priority_queue<int, std::vector<int>, std::greater<int>> min_q;//小顶堆
    std::priority_queue<int> max_q;//大顶堆
    MedianFinder() {
    }

    void addNum(int num) {
        max_q.push(num);//加到大顶堆
        min_q.push(max_q.top());//平衡
        max_q.pop();
        if (max_q.size() < min_q.size()) {//维护两个堆中的元素个数
            max_q.push(min_q.top());
            min_q.pop();
        }
    }

    double findMedian() {
        return max_q.size() > min_q.size() ? (double)max_q.top() : (max_q.top() + min_q.top()) * 0.5;
    }

};

—.

解题思路

参考剑指offer的思路,要划分出中位数x,则左边均小于x,右边均大于x
因此通过堆,可以设置左边为最大堆,堆顶即是左边的最大值,右边设置最大堆,堆顶即是右边的最小值;
通过两个堆的总size,
如果为奇数,则为中间数字,该值我们存放在minHeap的top中
如果为偶数,则为中间两个数/2.0,即minHeap.top()+maxHeap.top()/2
大家如果不明白,可以用[2,3,4]和[2,3,4,5]两个例子来手动模拟一下添加的过程,这样能有更清晰的认识

代码

class MedianFinder {
public:
	/** initialize your data structure here. */
	priority_queue<int,vector<int>,less<int>> maxHeap;//大顶堆
	priority_queue<int, vector<int>, greater<int>> minHeap;//小顶堆
	MedianFinder() {

	}
	void addNum(int num) {
		int size = maxHeap.size() + minHeap.size();
		/*
		为了保证数据平均分配到两个堆中,因此两个堆中数据的数目之差不能超过1
		因此可以假定总数目为偶数时,插入最小堆,否则插入最大堆
		如果当前总数目为偶数,插入最小堆
		*/
		if ((size&1)==0)//判断是否为偶数个
		{
			/*
				如果最大堆个数不为0
				且出现num比最大堆中的top还要小,如果直接插入最小堆(放到右边)
				是不行的,因为没有遵守右边均大于左边,因此要先插入到最大堆
				在最大堆中,取出top,再插入到最小堆
			*/
			if (maxHeap.size() > 0 && num < maxHeap.top()) {
				maxHeap.push(num);//入堆
				num = maxHeap.top();//去堆顶元素
				maxHeap.pop();//出堆
			}
			minHeap.push(num);//插入最小堆
		}
		//如果当前总数目为奇数,插入最大堆
		else
		{
			/*
				如果最小堆个数不为0
				且出现num比最小堆中的top还要大,如果直接插入最大堆(放到左边)
				是不行的,因为没有遵守左边均小于右边,因此要先插入到最小堆
				在最小堆中,取出top,再插入到最小堆
			*/
			if (minHeap.size()>0&&num> minHeap.top())
			{
				minHeap.push(num);
				num = minHeap.top();
				minHeap.pop();
			}
			maxHeap.push(num);//插入最大堆
		}
	}

	double findMedian() {
		int size = minHeap.size() + maxHeap.size();
		if (size == 0) return 0;//size为0
		if ((size&1))//判断是否为奇数个
		{
			return minHeap.top();
		}
		else//偶数
		{
			return (maxHeap.top() + minHeap.top()) / 2.0;
		}
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值