动态维护一个最大堆和一个最小堆,最大堆存储一半数据,最小堆存储一半数据,维持最大堆的堆顶比最小堆的堆顶小
偶数个数时,中位数就是两个堆顶的一半。奇数个数时,就是某一个堆顶。
添加元素时堆顶的调整:
1.最大堆与最小堆元素个数相同时:来一个数,这个数比最大堆堆顶小的话,添加进最大堆。这个数比最小堆堆顶大的话,push进最小堆
2.最大堆比最小堆多一个元素时:这个数比最大堆堆顶小的话,将最大堆堆顶push进最小堆,并在最大堆中弹出它,然后把新来的这个数push到最大堆。这个数比最大堆堆顶大的话,直接push到最小堆
3.最大堆比最小堆少一个元素时:刚好相反。如果来的这个数比最小堆堆顶大的话,将最小堆堆顶push到最大堆,然后在最小堆pop,将新来的数再添加到最小堆。如果新的这个数比最小堆堆顶小的话,Push到最大堆
class MedianFinder {
public:
/** initialize your data structure here. */
priority_queue<int> big_heap;
priority_queue<int,vector<int>,greater<int> > small_heap;
MedianFinder() {
}
void addNum(int num) {
if(big_heap.empty())
{
big_heap.push(num);
return;
}
if(big_heap.size() == small_heap.size())//
{
if(num<big_heap.top())
big_heap.push(num);
else
small_heap.push(num);
}
else if(big_heap.size() > small_heap.size())//
{
if(num > big_heap.top())
{
small_heap.push(num);
}else
{
small_heap.push(big_heap.top());
big_heap.pop();
big_heap.push(num);
}
}
else if(big_heap.size() < small_heap.size())//
{
if(num < small_heap.top())
big_heap.push(num);
else
{
big_heap.push(small_heap.top());
small_heap.pop();
small_heap.push(num);
}
}
}
double findMedian() {
if(big_heap.size() == small_heap.size())
return 1.0*(big_heap.top() + small_heap.top())/2;//注意乘以1.0,这个错误我找了很久,麻蛋
else if(big_heap.size() > small_heap.size())
return big_heap.top();
return small_heap.top();
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/