实现思路:
维护了一个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大数的思想,利用了最小堆,但实际上是有缺陷的
实现二思想:
而且要保证两种之间的个数相差≤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;
}
实现二最终提交结果
空间换时间,运行还是很快的