剑指offer-数据流中的中位数

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
 

解题思路

可以用一个最大堆实现中位数左边的数据容器,最小堆实现右边的数据容器。为了保证数据平均分配到两个堆中,在数据总数目是偶数时把新数据插入到最小堆,否则插入到最大堆。还要保证最大堆的所有数据都小于最小堆,以最大堆为例,当要插入到最大堆的数据大于最小堆最小数据时,可以先把此数据插入到最小堆中,再弹出最小堆最小数据并插入到最大堆中。同理当要插入到最小堆的数据小于最大堆最大数据时,可以先把此数据插入到最大堆中,再弹出最大堆最大数据并插入到最小堆中。

 

代码

 1 class Solution {
 2 public:
 3     void Insert(int num)
 4     {
 5         //总长度为偶数则插入到最小堆
 6         if((min.size()+max.size())%2 == 0){
 7             //若插入数字小于最大堆堆顶数字,则先插入到最大堆,再弹出最大堆堆顶数字插入到最小堆
 8             if(max.size() > 0&&num < max[0]){
 9                 max.push_back(num);
10                 push_heap(max.begin(), max.end(), less<int>());
11                 num = max[0];
12                 pop_heap(max.begin(), max.end(), less<int>());
13                 max.pop_back();
14             }
15             min.push_back(num);
16             push_heap(min.begin(), min.end(), greater<int>());
17         }
18         //总长度为奇数则插入到最大堆
19         else{
20             //若插入数字大于最小堆堆顶数字,则先插入到最小堆,再弹出最小堆堆顶数字插入到最大堆
21             if(min.size() > 0&&num > min[0]){
22                 min.push_back(num);
23                 push_heap(min.begin(), min.end(), greater<int>());
24                 num = min[0];
25                 pop_heap(min.begin(), min.end(), greater<int>());
26                 min.pop_back();
27             }
28             max.push_back(num);
29             push_heap(max.begin(), max.end(), less<int>());
30         }
31     }
32 
33     double GetMedian()
34     { 
35         if(min.size() == 0&&max.size() == 0)
36             return -1;
37         double res = 0;
38         if((min.size()+max.size())%2 == 0){
39             res = min[0]+max[0];
40             res /= 2;
41         }
42         else
43             res = min[0];
44         return res;
45     }
46 private:
47     vector<int> min;
48     vector<int> max;
49 };

 

posted @ 2018-04-06 17:41  FlyingWarrior  阅读(160)  评论(0编辑  收藏  举报