295. Find Median from Data Stream
-
题目思路
-
代码实现
- 1 code1
class MedianFinder
{
public:
/** initialize your data structure here. */
MedianFinder()
{
maxheapsize = 0;
minheapsize = 0;
}
void addNum(int num)
{
//1 和大根堆的堆顶元素进行比较
//比大根堆的堆顶元素大--->将元素插入的小根堆--->插入过程发现heapsize的差大于1--->小根堆弹出堆顶元素给大根堆,小根堆插入新元素
//比大根堆的堆顶元素小--->将元素插入到大根堆--->插入过程发现heapsize的差大于1--->大根堆弹出堆顶元素给小根堆,大根堆插入新元素
if (maxheapsize == 0)
{
maxheap.push_back(num);
make_heap(maxheap.begin(), maxheap.end());
maxheapsize++;
}
else
{
if (num > maxheap[0]) //num 比大根堆的堆顶大
{
if (minheapsize + 1 - maxheapsize > 1)
{
//先弹出 在插入
pop_heap(minheap.begin(), minheap.end(), std::greater<>{});
auto smallest = minheap.back();
minheap.pop_back();
minheapsize--;
//最大堆插入
maxheap.push_back(smallest);
push_heap(maxheap.begin(), maxheap.end());
maxheapsize++;
//最小堆插入
minheap.push_back(num);
push_heap(minheap.begin(), minheap.end(), std::greater<>{});
minheapsize++;
}
else
{
//将元素插入的小根堆
minheap.push_back(num);
push_heap(minheap.begin(), minheap.end(), std::greater<>{});
minheapsize++;
}
}
else // num <= 大根堆的堆顶
{
if (maxheapsize + 1 - minheapsize > 1)
{
//大根堆弹出堆顶元素给小根堆,大根堆插入新元素
//先弹出 在插入
pop_heap(maxheap.begin(), maxheap.end());
auto largest = maxheap.back();
maxheap.pop_back();
maxheapsize--;
//最小堆插入
minheap.push_back(largest);
push_heap(minheap.begin(), minheap.end(), std::greater<>{});
minheapsize++;
//最大堆插入
maxheap.push_back(num);
push_heap(maxheap.begin(), maxheap.end());
maxheapsize++;
}
else
{
//将元素插入大根堆
maxheap.push_back(num);
push_heap(maxheap.begin(), maxheap.end());
maxheapsize++;
}
}
}
} //end void addNum(int num)
double findMedian()
{
if (maxheapsize == 1 && minheapsize == 0)
{
return maxheap[0];
}
if ((maxheapsize + minheapsize) % 2 == 0)
{
//当前两个堆中的元素共偶数个
return double(maxheap[0] + minheap[0]) / 2;
}
else
{
return minheap[0];
}
}
private:
vector<int> maxheap; //大根堆
vector<int> minheap; //小根堆
int maxheapsize;
int minheapsize;
};
- 2 code2
class MedianFinder
{
public:
/** initialize your data structure here. */
MedianFinder()
{
maxheapsize = 0;
minheapsize = 0;
}
void addNum(int num)
{
if (minheapsize == 0)
{
minheap.push_back(num);
make_heap(minheap.begin(), minheap.end(), std::greater<>{});
minheapsize++;
}
else
{
if (num <= minheap[0]) //num <= 小根堆的堆顶
{
//应该插入大根堆 下面就插入大根堆的情况进行讨论
if (maxheapsize + 1 - minheapsize > 1)
{
//大根堆弹出堆顶元素给小根堆,大根堆插入新元素
//先弹出 在插入
pop_heap(maxheap.begin(), maxheap.end());
auto largest = maxheap.back();
maxheap.pop_back();
maxheapsize--;
//最小堆插入
minheap.push_back(largest);
push_heap(minheap.begin(), minheap.end(), std::greater<>{});
minheapsize++;
//最大堆插入
maxheap.push_back(num);
push_heap(maxheap.begin(), maxheap.end());
maxheapsize++;
}
else
{
//直接插入大根堆
maxheap.push_back(num);
push_heap(maxheap.begin(), maxheap.end());
maxheapsize++;
}
}
else // num > 小根堆的堆顶
{
//应该插入小根堆 下面就插入小根堆的情况进行讨论
if (minheapsize + 1 - maxheapsize > 1)
{
//先弹出 在插入
pop_heap(minheap.begin(), minheap.end(), std::greater<>{});
auto smallest = minheap.back();
minheap.pop_back();
minheapsize--;
//最大堆插入
maxheap.push_back(smallest);
push_heap(maxheap.begin(), maxheap.end());
maxheapsize++;
//最小堆插入
minheap.push_back(num);
push_heap(minheap.begin(), minheap.end(), std::greater<>{});
minheapsize++;
}
else
{
//直接插入小根堆
minheap.push_back(num);
push_heap(minheap.begin(), minheap.end(), std::greater<>{});
minheapsize++;
}
}
}
} //end void addNum(int num)
double findMedian()
{
if (minheapsize == 1 && maxheapsize == 0)
{
return minheap[0];
}
if ((maxheapsize + minheapsize) % 2 == 0)
{
return double(maxheap[0] + minheap[0]) / 2;
}
else //奇数个
{
return maxheap[0];
}
}
private:
vector<int> maxheap; //大根堆
vector<int> minheap; //小根堆
int maxheapsize;
int minheapsize;
};
code2对于递增序列,如{1,2,3,4,5}输出的值不正确。
code1和code2都是有问题的代码,稍后将正确代码上传。
- 正确的代码
code1和code2使用递减序列和递增序列就能测出来代码有问题,去网上参考了一下其他人的代码,正确代码如下:
class MedianFinder
{
public:
MedianFinder()
{
}
void addNum(int num)
{
if (l_.empty() || num <= l_.top())
{
l_.push(num);
}
else
{
r_.push(num);
}
//step2
if (l_.size() < r_.size())
{
l_.push(r_.top());
r_.pop();
}
else if (l_.size() - r_.size() == 2)
{
r_.push(l_.top());
l_.pop();
}
}
double findMedian()
{
if (l_.size() > r_.size())
{
return static_cast<double>(l_.top());
}
else
{
return (static_cast<double>( l_.top() + r_.top() )) / 2;
}
}
private:
priority_queue<int, vector<int>, less<int>> l_;
priority_queue<int, vector<int>, greater<int>> r_;
};
- 参考资料:
1 https://www.youtube.com/watch?v=60xnYZ21Ir0 《花花酱 LeetCode 295. Find Median from Data Stream - 刷题找工作 EP51》