题目描述
问题分析
使用大小堆来完成:
我们让最大堆总是大于最小堆一个量或者等于最小堆数量,中位数只可能是最大堆顶或最大堆与最小堆堆顶平均值。
c++代码
class MedianFinder {
public:
//大顶堆 + 小顶堆 的方法
//小顶堆
priority_queue<int, vector<int>, greater<int>> minHeap;
//大顶堆
priority_queue<int> maxHeap;
MedianFinder() {
}
// 时间复杂度为O(logn)
//如果整个列表的长度为n的话
//那么大顶堆就用于存储前k个较小的元素,因为大顶堆中的堆顶的元素值最大
//而小顶堆就用于存储后n-k个较大的元素,因为小顶堆中的堆顶的元素值最小
//k和n-k还必须满一个条件:那就是当n为偶数时,k=n-k;当n为奇数时,k=n-k+1;必须满足这个等式
//当n为偶数时,中位数等于(大顶堆堆顶值 + 小顶堆堆顶值)/ 2
//当n为奇数时,中位数就等于大顶堆堆顶值
void addNum(int num) {
//为空直接存
if (maxHeap.empty()) {
maxHeap.push(num);
return;
}
if (num <= maxHeap.top()) maxHeap.push(num);
else minHeap.push(num);
//最大堆只能比最小堆多一个元素,或者两者相等
if (maxHeap.size() > minHeap.size() + 1) {
minHeap.push(maxHeap.top());
maxHeap.pop();
}
//最大堆不能比最小堆中的元素少
if (maxHeap.size() < minHeap.size()) {
maxHeap.push(minHeap.top());
minHeap.pop();
}
}
double findMedian() {
if (maxHeap.size() == minHeap.size() + 1) { //大顶堆元素数量比小顶堆元素数量多一
return maxHeap.top();
}
else { //大顶堆元素数量 = 小顶堆元素数量
return (maxHeap.top() + minHeap.top()) * 0.5;
}
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/