中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-median-from-data-stream
class MedianFinder {
priority_queue<int> front;
priority_queue<int, vector<int>, greater<int>> back;
// 把数据分为两段,前面的小,后面的大
// 为了方便把数字从前面移到后面-> 总是移动前面的最大的到后面
// 为了方便把数字从后面移到前面-> 总是移动后面最小的到前面
// 所以数据的前半部分用大堆
// 数据的后半部分用小堆
public:
/** initialize your data structure here. */
MedianFinder() {
}
void addNum(int num) {
// 我们总是把数字加到前面
// 如果前面的比后面的多
// 那么就把前面较大的取出来,放到后面
front.push(num);
while (front.size() > back.size()) {
auto l = front.top();
front.pop();
back.push(l);
}
// 再看一下大小
// 如果前半部分有数大于后半部分,那么需要交换
if (!front.empty() && !back.empty()) {
while (back.top() < front.top()) {
auto f = front.top();
front.pop();
auto b = back.top();
back.pop();
front.push(b);
back.push(f);
}
}
}
double findMedian() {
if (front.size() == back.size()) {
if (!front.empty()) {
return (double)(front.top() + back.top())/2;
}else{
return 0;
}
}else{
return back.empty() ? 0 : back.top();
}
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/