如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
题解
解法1
使用插入排序维护一个排好序的vector数组,Insert时间复杂度O(n),GetMedian()时间复杂度O(1)
class Solution {
public:
void Insert(int num)
{
haha.push_back(num);
for(int i = haha.size() - 1; i > 0 && haha[i] < haha[i - 1]; i--) swap(haha[i], haha[i - 1]);
}
double GetMedian()
{
int s = haha.size();
return s % 2 ? haha[s/2] : (haha[s/2] + haha[s/2-1]) / 2.0;
}
private:
vector<int> haha;
};
解法2
维护一个大根堆和小根堆,保证大根堆所有的数小于小根堆中所有的数。Insert时间复杂度O(log(n)),GetMedian()时间复杂度O(1)
所以每次如果num小于大堆顶,插入大堆,否则插入小堆。(第一次插入大堆)
若大堆比小堆个数多1个以上,则从大堆中弹出堆顶元素并插入到小堆中,
若小堆个数少于大堆,则从小堆中弹出堆顶元素并插入大堆中
class Solution {
public:
void Insert(int num)
{
if(maxtop.empty() || num < maxtop.top()) maxtop.push(num);
else mintop.push(num);
if(maxtop.size() == mintop.size() + 2){
mintop.push(maxtop.top());
maxtop.pop();
}
if(maxtop.size() < mintop.size()){
maxtop.push(mintop.top());
mintop.pop();
}
}
double GetMedian()
{
return maxtop.size() == mintop.size() ? (maxtop.top() + mintop.top()) / 2.0 : maxtop.top();
}
private:
priority_queue<int, vector<int>, less<int> > maxtop; //大顶堆
priority_queue<int, vector<int>, greater<int> > mintop; //小顶堆
};