數據流中的中位數


題目

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

思路

  使容器左邊的數都小於右邊的數,即使左右兩邊的數沒有排序,也能根據左邊最大的數和右邊最小的數來實現查中位數。所以左邊用大頂錐實現,右邊用小頂錐實現。只需要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;
}

 code

class Solution {
public:
    void Insert(int num)
    {
        if(max.empty()||num<=max.top())
            max.push(num);
        else
            min.push(num);
        //左邊的大頂錐最多比右邊的小頂錐的容量大一(奇數)
        if(max.size()==min.size()+2)
        {
            min.push(max.top());
            max.pop();
        }
        //最后返回的是左邊的大頂錐錐頂,所以右邊的小頂錐不能比左邊的大頂錐容量大
        if(max.size()+1==min.size())
        {
            max.push(min.top());
            min.pop();
        }
        return ;
    }

    double GetMedian()
    { 
        return max.size()==min.size()?(max.top()+min.top())/2.0:max.top();
    }
private:
    priority_queue<int,vector<int>,less<int>> max;
    priority_queue<int,vector<int>,greater<int>> min;
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM