数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
解法1:数组不排序,基于Partition函数找中位数。插入数字和找出中位数的时间复杂度分别为O(1)和O(n)
1 class Solution { 2 public: 3 int Partition(vector<int> &arr, int begin, int end) 4 { 5 int tmp=arr[begin]; 6 while(begin<end) 7 { 8 while(begin<end && arr[end]>=tmp)--end; 9 arr[begin]=arr[end]; 10 while(begin<end && arr[begin]<=tmp)++begin; 11 arr[end]=arr[begin]; 12 } 13 arr[begin]=tmp; 14 return begin; 15 } 16 void Insert(int num) 17 { 18 arr.push_back(num); 19 } 20 double GetMedian() 21 { 22 int length=arr.size(); 23 if(length==0)return 0; 24 if(length & 1) 25 { 26 int begin=0; 27 int end=length-1; 28 while(true) 29 { 30 int mid=Partition(arr, begin, end); 31 if(mid==length/2)break; 32 if(mid>length/2)end=mid-1; 33 else begin=mid+1; 34 } 35 return arr[length/2]; 36 }else{ 37 int begin=0; 38 int end=length-1; 39 while(true)//确定length/2位置上的数 40 { 41 int mid=Partition(arr, begin, end); 42 if(mid==length/2)break; 43 if(mid>length/2)end=mid-1; 44 else begin=mid+1; 45 } 46 begin=0; 47 end=length/2-1; 48 while(true)//确定length/2-1位置上的数 49 { 50 int mid=Partition(arr, begin, end); 51 if(mid==end)break; 52 else begin=mid+1; 53 } 54 return (arr[length/2-1]+arr[length/2])*1.0/2; 55 } 56 } 57 private: 58 vector<int> arr; 59 };
解法2:数组插入元素后保持排序,故插入数字和找出中位数的时间复杂度分别为O(n)和O(1)
1 class Solution { 2 public: 3 void Insert(int num) 4 { 5 arr.push_back(num); 6 size_t idx; 7 for(idx=arr.size()-2; idx>=0; --idx)//后移 8 { 9 if(arr[idx]>num)arr[idx+1]=arr[idx]; 10 else break; 11 } 12 arr[idx+1]=num;//插入 13 } 14 double GetMedian() 15 { 16 int length=arr.size(); 17 if(length & 1) 18 { 19 return arr[length/2]; 20 }else{ 21 return (arr[length/2-1]+arr[length/2])*1.0/2; 22 } 23 } 24 private: 25 vector<int> arr; 26 };
解法3:用一个大顶堆实现数组左边的数据容器,用一个小顶堆实现数组右边的数据容器。插入数字和找出中位数的时间复杂度分别为O(logn)和O(1)
1 class Solution { 2 public: 3 void Insert(int num) 4 { 5 if((max.size()+min.size()) & 1)//如果总数是奇数个,插入大顶堆,并保证大顶堆的所有数据都小于小顶堆中的数据 6 { 7 if(min.size()>0 && num>min[0]) 8 { 9 min.push_back(num); 10 push_heap(min.begin(), min.end(), std::greater<int>()); 11 num=min[0]; 12 pop_heap(min.begin(), min.end(), std::greater<int>()); 13 min.pop_back(); 14 } 15 max.push_back(num); 16 push_heap(max.begin(), max.end(), std::less<int>()); 17 }else{//如果总数是偶数个,插入小顶堆,并保证大顶堆中所有数据都小于小顶堆中的数据 18 if(max.size()>0 && num<max[0]) 19 { 20 max.push_back(num); 21 push_heap(max.begin(), max.end(), std::less<int>()); 22 num=max[0]; 23 pop_heap(max.begin(), max.end(), std::less<int>()); 24 max.pop_back(); 25 } 26 min.push_back(num); 27 push_heap(min.begin(), min.end(), std::greater<int>()); 28 } 29 } 30 double GetMedian() 31 { 32 if(min.size()==0)return 0; 33 if((min.size()+max.size()) & 1) 34 { 35 return min[0]; 36 }else{ 37 return (min[0]+max[0])*1.0/2; 38 } 39 } 40 private: 41 vector<int> max; 42 vector<int> min; 43 };