感觉这道题的复杂程度还是比较高的,参考了书里的内容,利用书中一模一样的思路,完成了程序。
程序的基本思路是将插入的数据等分为两个部分,并且左边部分的所有数字都小于右边部分。堆排序是一个比较方便的办法,它的插入复杂度是 O(logn),而得到中位数的复杂度是 O(1),时间效率非常高。具体的思路是左侧使用最大堆来实现,堆顶可以获取左侧部分的最大元素,而右侧使用最小堆实现,堆顶可以获取右侧的最小元素,而最小堆中的元素永远大于最大堆中的元素。
为了保证数据的平均分配,可以在之前插入数据的数目为奇数的时候,就插入到最大堆中,否则就插入到最小堆中。但是如果在插入最小堆的时候发现它比最大堆中的最大元素还要小,说明这个数字应该插入左侧的最大堆中,这时候就需要先把数字插入最大堆中,然后再对最大堆排序,弹出最大堆堆顶的最大元素,插入到最小堆中。
在获取中位数的时候,由于第一个元素插入到最小堆中,所以如果是奇数个元素的话,就获取最小堆堆顶的元素,如果是偶数的话,就获取最大堆和最小堆堆顶的元素并取平均值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| class Solution { private: vector<int> min; vector<int> max; public: void Insert(int 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<int>()); num=max[0]; pop_heap(max.begin(),max.end(),less<int>()); max.pop_back(); } min.push_back(num); push_heap(min.begin(),min.end(),greater<int>()); }else{ if(min.size()>0 && num>min[0]){ min.push_back(num); push_heap(min.begin(),min.end(),greater<int>()); num=min[0]; pop_heap(min.begin(),min.end(),greater<int>()); min.pop_back(); } max.push_back(num); push_heap(max.begin(),max.end(),less<int>()); } }
double GetMedian() { int len=min.size()+max.size(); if(len==0) return 0.0; double median; if((len&1)==0){ median=((double)min[0]+(double)max[0])/2; }else{ median=(double)min[0]; } return median; }
};
|