【剑指offer】55.数据流中的中位数
总目录:
1.问题描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
数据范围:数据流中数个数满足 1<n<100,大小满足 1≤val≤1000 
进阶: 空间复杂度 O(n), 时间复杂度 O(nlogn)
进阶: 空间复杂度 O(n), 时间复杂度 O(nlogn)
2.问题分析
用一个buffer来缓存已经接收到的数据,使用某种规则保证其有序,取中位数时直接按索引取即可,关键在于如何使其在满足时空复杂度的前提下有序。
0链表
用链表来保存数据,不仅插入快,而且用两个指针维护中间点/中间两个点,可以实现O(n)的存入,O(1)的读取。
1插入排序
使用vector作buffer,每次插入新数据,然后向前插入到有序集合中
2堆排序
中位数是指:有序数组中中间的那个数。则根据中位数可以把数组分为如下三段:[中位数的左边,中位数,中位数的右边]。
使用一个大根堆保存左边较小的数据left_q,使用一个小根堆保存右边较大的数据right_q。
如果left_q.Size=right_q.Size+1,则中间值=left_q.Top;
如果left_q.Size=right_q.Size-1,则中间值=right_q.Top;
如果left_q.Size=right_q.Size,则中间值=(left_q.Top+right_q.Top)/2;
那么存在2个关键问题:
(1)如何维护这两个堆,进来的数值应该存到哪个堆中,
(2)要注意保持两个堆的平衡,两个堆的大小之差最大为1;
解决策略是先放到一个堆中,然后取其Top再放到另一个堆中,此时进行堆平衡、从过大的堆中取出元素放入较小的堆中直到达到允许的平衡状态(尺寸之差不超过1)。
3.代码实例
插入排序法
 
1 class Solution { 2 public: 3 //维护一个堆 4 #define SCD static_cast<double> 5 6 vector<int> buffer; 7 void Insert(int num) { 8 //插入排序 9 buffer.push_back(num); 10 int numSize = buffer.size(); 11 for (int cur = numSize - 1; cur != 0; cur--) { 12 //停止插入 13 if (buffer[cur - 1] < buffer[cur]) { 14 return;; 15 } 16 17 //和前一个交换 18 swap(buffer[cur - 1], buffer[cur]); 19 } 20 21 } 22 23 double GetMedian() { 24 int sz = buffer.size(); 25 if (sz & 1) { 26 return SCD(buffer[sz >> 1]); 27 } else { 28 return SCD(buffer[sz >> 1] + buffer[(sz - 1) >> 1]) / 2; 29 } 30 return 0; 31 } 32 33 };
堆排序法
 
1 class Solution { 2 public: 3 #define SCD static_cast<double> 4 priority_queue<int> min_q; // 大顶推 5 priority_queue<int, vector<int>, greater<int>> max_q; // 小顶堆 6 7 void Insert(int num) { 8 9 min_q.push(num); // 试图加入到大顶推 10 11 //换出min_q中的最大值 12 max_q.push(min_q.top()); 13 min_q.pop(); 14 15 //平衡两个堆 16 //这里保证了min_q和max_q的元素数量之差不会超过1 17 if (min_q.size() < max_q.size()) { 18 min_q.push(max_q.top()); 19 max_q.pop(); 20 } 21 } 22 23 double GetMedian() { 24 //下面语句的意思是尽量保证min_q.Size>=max_q.Size,不允许min_q.Size<max_q.Size 25 return min_q.size() > max_q.size() ? SCD(min_q.top()) : SCD( 26 min_q.top() + max_q.top()) / 2; 27 } 28 29 };
 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号