数据流中的中位数(六十三)
题目描述:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
代码(已在牛客上 AC)
这道题听说有很多思路, 但是呢各种方法的时间或空间复杂度不同. 这里采用的是两个堆, 使用最大堆保存数据流中较小的数, 使用最小堆保存数据流中较大的数, 这样的话, (qmin.top() + qmax.top()) / 2.
就是中位数(偶数情况下);
而对于奇数情况, 在两个堆中的数据为偶数的情况下, 对于插入的元素, 总是向最小堆中插入; 即奇数情况下, qmin
中的元素总比 qmax
多一个.
// 1. 保证最小堆 qmin 中的元素都大于最大堆 qmax 中的元素
// 2. 对于插入新元素, 如果当前两个堆中的元素个数之和为偶数, 就将新元素插入到最小堆中;
// 否则插入到最大堆 qmax 中.
class Solution {
public:
void Insert(int num) {
if ((qmax.size() + qmin.size()) % 2) {
qmin.push(num);
qmax.push(qmin.top());
qmin.pop();
}
else {
qmax.push(num);
qmin.push(qmax.top());
qmax.pop();
}
}
double GetMedian() {
if (qmax.empty() && qmin.empty()) return 0.0;
if ((qmax.size() + qmin.size()) % 2) return double(qmin.top());
else return double((qmax.top() + qmin.top())) / 2.;
}
private:
priority_queue<int, vector<int>, less<int>> qmax; // 最大堆放小值
priority_queue<int, vector<int>, greater<int>> qmin; // 最大堆放小值
};