題意:有n個操作,存入數字,和輸出中位數
題解:要確保輸入數字的操作和輸出中位數的操作,都是低於等於Log(n)的效率。
那麼怎麼做呢?我們維護兩個multiset
中位數顯然就是A裏的最小值和B裏的最大值中選擇。那麼在存數字的時候判斷這個數字應該放到哪個樹裏,然後再需要判斷A,B的元素數量差,如果出現差值大於1,就要把較多的那個樹的某個極值元素放到較小的那個樹裏,始終保持兩個樹的元素數量差不超過1,所以存入數字的效率是O(logn*3)
而取中位數是O(1)的效率
不知道爲什麼multiset的size()函數,會超時,難道是O(n)的效率取size嗎?介紹裏明明是constant的時間複雜度啊。
用優先隊列也可以的。效率是一樣的。
class MedianFinder {
public:
/** initialize your data structure here. */
multiset<int> m1;
multiset<int> m2;
int n=0;
int len1;
int len2;
MedianFinder() {
m1.clear();
m2.clear();
len1=0;
len2=0;
}
void addNum(int num) {
if(len1==0&&len2==0)
{
m1.insert(num);
len1++;
n++;
return;
}
multiset<int>::iterator it = prev(m1.end());
if(num < *it)
{
m1.insert(num);
len1++;
}
else
{
m2.insert(num);
len2++;
}
if(len1<len2-1)
{
m1.insert(*m2.begin());
len1++;
m2.erase(m2.begin());
len2--;
}
if(len1-1>len2)
{
m2.insert(*prev(m1.end()));
len2++;
m1.erase(prev(m1.end()));
len1--;
}
n++;
}
double findMedian() {
if(n&1)
{
if(len1<len2)
return *m2.begin();
else
return *prev(m1.end());
}
else
return 1.0*(*prev(m1.end())+*m2.begin())/2;
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/