【LeetCode295】-数据流的中位数

实现思路:

维护了一个k大小的最小堆minq,该最小堆里面存储的实际上前k最大的数据,k=n/2+1,由于k的数值是在变换了,往里新添加的数据有可能新来的元素,也可能是之前未添加进去的元素,所以我还维护了一个最大堆otherq,里面放置的是未添加到minq的数据

  • 当前minq堆中元素<k时
    • otherq中没有元素时,将新来的元素直接压入minq中
    • otherq中有元素的情况下,谁大谁就保存在minq中,否则就保存在otherq中
  • 当前minq堆中元素 ≥ k时
    • 和minq栈顶元素比,谁大谁就保存在minq中,否则就保存在otherq中

实现代码(未过):

不知道为什么,我在本地测试报错的样例得到的结果是正确的,但一到LeetCode上就错了,太奇怪了

#include <iostream>
#include <queue>
using namespace std;
class MedianFinder {
public:
	int n;
	priority_queue<int, vector<int>, greater<int>> minq;
	priority_queue<int> otherq;
	/** initialize your data structure here. */
	MedianFinder() {
		n = 0;
	}

	void addNum(int num) {
		n++;
		int nn = n  / 2+1;
		if (minq.size() < nn) {
			if (otherq.size() > 0)
			{
				if (num > otherq.top())
					minq.push(num);
				else {
					minq.push(otherq.top());
					otherq.pop();
					otherq.push(num);
				}
			}
			else{ minq.push(num); }
		}
		else {
			if (num > minq.top()) {
				otherq.push(minq.top());
				minq.pop();
				minq.push(num);
			}
			else
			{
				otherq.push(num);
			}
		}
	}

	double findMedian() {
		if (n % 2) return minq.top()/1.0;
		else {
			int n1 = minq.top();minq.pop();
			int n2 = minq.top();
			minq.push(n2);
			minq.push(n1);
			return (n1 + n2)/2.0;
		}
	}
};
int main() {
	MedianFinder m;
	m.addNum(-1);
	m.addNum(-2);
	m.addNum(-3);
	m.addNum(-4);
	//m.addNum(-5);
	cout << m.findMedian();
	return 0;
}
依次压入-1,-2,-3,-4我在本地测完得-2.5,到LeetCode测完就变-1.5了,看问题好像是错在没有考虑之前没有入minq的元素有可能比新来的元素大的问题,可是我改正的代码修复了这个问题,实在想不明白问题出在哪儿里了

实现一评价与思考:

这种实现的情况下,我是延续了 【LeetCode215】- 第K大数的思想,利用了最小堆,但实际上是有缺陷的

在这里插入图片描述


实现二思想:

提示:这里填写该问题的具体解决方案:例如:新建一个 Message 对象,并将读取到的数据存入 Message,然后 mHandler.obtainMessage(READ_DATA, bytes, -1, buffer).sendToTarget();换成 mHandler.sendMessage()。

而且要保证两种之间的个数相差≤1,两个堆的大小相同时,栈顶相加除二,否则个数多的那个堆的栈顶为中位数

我之前也想过这种方式,但考虑的不全面,只单纯的个数满足存一半一半的情况,但没有限制最大堆的栈顶要小于最小堆的栈顶

在这里插入图片描述在这里插入图片描述在这里插入图片描述总结来说就是要保证最大堆中的元素都要要与最小堆中元素,且两个堆中元素个数之差不超过1

实现二代码

#include <iostream>
#include <queue>
using namespace std;

class MedianFinder {
public:
	/** initialize your data structure here. */
	priority_queue<int> maxq;
	priority_queue<int, vector<int>, greater<int>> minq;
	MedianFinder() {
		
	}

	void addNum(int num) {
		if (maxq.empty() && minq.empty())
			maxq.push(num);
		else if (maxq.size() == minq.size()) {
			if (num < maxq.top())
			{
				maxq.push(num);
			}
			else {
				minq.push(num);
			}
		}
		else if (maxq.size() > minq.size()) {
			if (num > maxq.top())
			{
				minq.push(num);
			}
			else {
				minq.push(maxq.top());
				maxq.pop();
				maxq.push(num);
			}
		}
		else if (minq.size() > maxq.size()) {
			if (num < minq.top()) {
				maxq.push(num);
			}
			else {
				maxq.push(minq.top());
				minq.pop();
				minq.push(num);
			}
		}
	}

	double findMedian() {
		if (maxq.size() == minq.size()) {
			return (maxq.top() + minq.top()) / 2.0;
		}
		else if (maxq.size() > minq.size())
		{
			return maxq.top() / 1.0;
		}
		return minq.top() / 1.0;
	}
};
int main() {
	MedianFinder m;
	m.addNum(-1);
	m.addNum(-2);
	m.addNum(-3);
	m.addNum(-4);
	m.addNum(-5);
	cout << m.findMedian();
	return 0;
}

实现二最终提交结果

在这里插入图片描述 空间换时间,运行还是很快的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值