題目
如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那么中位數就是所有數值排序之后位於中間的數值。如果從數據流中讀出偶數個數值,那么中位數就是所有數值排序之后中間兩個數的平均值。
思路
使容器左邊的數都小於右邊的數,即使左右兩邊的數沒有排序,也能根據左邊最大的數和右邊最小的數來實現查中位數。所以左邊用大頂錐實現,右邊用小頂錐實現。只需要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; };