剑指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 };