题目
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
示例:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2
进阶:
如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?
解题思路:
创建两个堆,将前一半数据(小的一半)放到一个极大堆里面,将后一半数据(大的一半)放到一个极小堆里面即可,然后当数据总量为计数的时候选出对应的极值,当数据量为偶数的时候,选出两个堆的极值然后求均值即可。
具体代码如下:
class MedianFinder {
private:
vector<int> first{}; //the small nums, a max heap, when singular, push to it!
vector<int> second{}; //the big nums, a min heap, when odd, push to it!
public:
/** initialize your data structure here. */
MedianFinder() {}
void addNum(int num)
{
if ((first.size() + second.size()) % 2 == 0) //odd, push the num to the second
{
if (first.size() > 0 && num < first[0])
{
first.push_back(num);
push_heap(first.begin(), first.end(), less<int>());
num = first[0];
pop_heap(first.begin(), first.end(), less<int>());
first.pop_back();
}
second.push_back(num);
push_heap(second.begin(), second.end(), greater<int>());
}
else
{
if (second.size() > 0 && num > second[0])
{
second.push_back(num);
push_heap(second.begin(), second.end(), greater<int>());
num = second[0];
pop_heap(second.begin(), second.end(), greater<int>());
second.pop_back();
}
first.push_back(num);
push_heap(first.begin(), first.end(), less<int>());
}
}
double findMedian()
{
double res;
if ((first.size() + second.size()) == 0) return -1;
if (((first.size() + second.size())) % 2 == 0)
{
res = ((double)(first[0] + second[0])) / 2;
return res;
}
if ((first.size() + second.size()) % 2 == 1)
{
return (double)second[0];
}
return -1;
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/