1. 程式人生 > >數據流中的中位數

數據流中的中位數

ace span clas 彈出 eap pre esp number 需要

題目

  如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麽中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麽中位數就是所有數值排序之後中間兩個數的平均值。

思路

  使容器左邊的數都小於右邊的數,即使左右兩邊的數沒有排序,也能根據左邊最大的數和右邊最小的數來實現查中位數。所以左邊用大頂錐實現,右邊用小頂錐實現。只需要O(1)的時間就可以實現的到頂錐的數據。

  如果數據總數目是偶數,插入小頂錐,否則插入大頂錐。要保證大頂錐中的數字都小於小頂錐中的數字,如果是偶數時,插入小頂錐,如果此時的數據比小頂錐中的數據小,怎麽辦?

  解決:

    插入小頂錐時,先把數據插入大頂錐,接著把大頂錐中最大數字拿出來插入小頂錐,最終插入的數字就是原大頂錐中最大的數字,這樣就保證了小頂錐中的數字都比大頂錐中的數字大。

    插入大頂錐與插入小頂錐類似...

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

template <typename T>
class Solution
{
    public:
        void insert(T &num);
        T get_num();
    private:
        vector<T> min;//右邊最小堆--第一個數字最小 
        vector<T> max;//
左邊最大堆---第一個數字最大 }; template <typename T> void Solution<T>::insert(T &num) { if(((min.size()+max.size())&1)==0)//偶數 { if(max.size()>0&&num<max[0]) { max.push_back(num); push_heap(max.begin(),max.end(),less<T>());//升序 num
=max[0]; pop_heap(max.begin(),max.end(),less<T>());//將第一個元素與最以後一個元素替換 max.pop_back();//彈出最後一個元素 } min.push_back(num); push_heap(min.begin(),min.end(),greater<T>());//降序 } else { if(min.size()>0&&min[0]<num) { min.push_back(num); push_heap(min.begin(),min.end(),greater<T>()); num=min[0]; pop_heap(min.begin(),min.end(),greater<T>()); min.pop_back(); } max.push_back(num); push_heap(max.begin(),max.end(),less<T>()); } } template<typename T> T Solution<T>::get_num() { int size=max.size()+min.size(); if(!size) { cerr<<"no number available"<<endl; return 0x3f3f; } int mid=0; if(size&1) return min[0]; else return (min[0]+max[0])/2; } int main() { vector<int> v{1,4,9,7,5,6}; Solution<int> s; for(int i=0;i<v.size();++i) { s.insert(v[i]); } if(s.get_num()!=0x3f3f) cout<<s.get_num()<<endl; else { cerr<<"數組有誤."<<endl; return 0; } return 0; }

數據流中的中位數