剑指offer 面试题. 数据流中的中位数

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

 

解答:

这题没做过,用一个最大堆和一个最小堆来夹逼中位数,记录一下这个方法。

限制条件有两个:

1.最大堆的数都比最小堆小,这一点可以通过二者的top来限制(即限制最大堆的top小于最小堆的top)。

2.最小堆的size要么等于最大堆的size,要么比最大堆的size大1。这是什么意思呢,举个栗子:

最大堆:1,2,3,4

最小堆:6,7,8,9(当然这里不符合堆的性质,只是举例其中含有的数字)

那么此时二者size相同,中位数就是最小堆的top。

如果最小堆多一个10,即此时最小堆为:6,7,8,9,10

那么中位数就恰好是最大堆的top和最小堆的top的平均数。

 

另外一点就是priority_queue默认是最大堆,greater<int>是最小堆,less<Int>是最大堆,下次记住吧。。。。

代码:

 1 class Solution {
 2 public:
 3     priority_queue<int,vector<int>,less<int>> heap_le;
 4     priority_queue<int,vector<int>,greater<int>> heap_ri;
 5     void Insert(int num)
 6     {
 7         if(heap_le.empty() or heap_le.top()>=num){
 8             heap_le.push(num);
 9         }
10         else{
11             heap_ri.push(num);
12         }
13         while(not heap_le.empty() and not heap_ri.empty() and heap_le.top()>heap_ri.top()){//保持性质1
14             heap_ri.push(heap_le.top());
15             heap_le.pop();
16         }
17         while(heap_le.size()>heap_ri.size()){//保持性质2
18             heap_ri.push(heap_le.top());
19             heap_le.pop();
20         }
21         while(heap_le.size()<heap_ri.size()-1){//保持性质2
22             heap_le.push(heap_ri.top());
23             heap_ri.pop();
24         }
25     }
26 
27     double GetMedian()
28     { 
29         return (heap_le.size()+heap_ri.size())%2?heap_ri.top()*1.0:(heap_le.top()+heap_ri.top())/2.0;
30     }
31 };

2020-02-14 15:14:57

posted @ 2020-02-14 15:15  NeoZy  阅读(125)  评论(0编辑  收藏  举报