题目描述
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[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
解题思路:动态维护一个最大堆和一个最小堆,最大堆存储一半元素最小堆存储一半元素,维持最大堆的堆顶比最小堆的堆顶小。
1.当最大堆与最小堆元素个数相同时,新元素小于最大堆,就push进最大堆,反之则入最小堆。
2.当最大堆比最小堆多一个元素:
(1)如果新元素小于最大堆堆顶:经最大堆的堆顶push进入最小堆,将最大堆的堆顶移除,将新元素添加到最大堆。
(2)如果新元素大与最大堆堆顶,竟新元素直接push到最小堆。
3.当最大堆比最小堆少一个元素:
(1)如果新元素小于最小堆的堆顶,将新元素直接push进入最大堆。
(2)如果新元素大与最小堆堆顶,将最小堆的堆顶push进入最大堆,将最小堆的堆顶一出,将新元素添加至最小堆。
4.最后获取中位数。
(1)最大堆最小堆中的元素个数相同时,中位数是最大堆堆顶与最小堆堆顶的平均值。
(2)最大堆比最小堆多一个元素时,中位数是最大堆的堆顶。
(3)最大堆比最小堆少一个元素,中位数是最小堆堆顶。
下面是我的代码,因为思路写的已经很全所以么有些注释,其实就是按照思路一步一步走就可以了。
、
class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder() {
}
void addNum(int num) {
if(big_heap.empty()){
big_heap.push(num);
return;
}
if(big_heap.size()==small_heap.size()){
if(num>big_heap.top()){
small_heap.push(num);
}else{
big_heap.push(num);
}
}else if(big_heap.size()>small_heap.size()){
if(num>big_heap.top()){
small_heap.push(num);
}else{
small_heap.push(big_heap.top());
big_heap.pop();
big_heap.push(num);
}
}else if(big_heap.size()<small_heap.size()){
if(num<small_heap.top()){
big_heap.push(num);
}else{
big_heap.push(small_heap.top());
small_heap.pop();
small_heap.push(num);
}
}
}
double findMedian() {
if (big_heap.size()==small_heap.size()){
return (big_heap.top()+small_heap.top())/2.0;
}else if(big_heap.size()>small_heap.size()){
return big_heap.top();
}else{
return small_heap.top();
}
}
private:
priority_queue<int ,vector<int >,less<int>> big_heap;
priority_queue<int ,vector<int >,greater<int>> small_heap;
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/