Find Median from Data Stream - LeetCode
题目:
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples:
[2,3,4] , the median is 3
[2,3], the median is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:
1.void addNum(int num) - Add a integer number from the data stream to the data structure.
2.double findMedian() - Return the median of all elements so far.
这道题要我们找中位数。看到题目后有两种想法,第一种是插入的时候保持顺序,然后找中位数时根据数组长度算出中位数;第二种始终记录中位数的位置,插入的时候保持顺序,并且更改指向中位数的指针,findMedian()时只需根据指针,以及数组元素个数的奇偶来判断。
实际尝试下来第二种效率更高
class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder() {
it = myset.end();
isodd = false;
}
void addNum(int num) {
myset.insert(num);
if (it == myset.end()) {
it = myset.begin();
isodd = true;
} else {
if (*it > num && isodd == true) {
it--;
} else if(*it <= num && isodd == false) {
it++;
}
isodd = !isodd;
}
}
double findMedian() {
if (isodd) {
return *it;
} else {
double a =*it, b = *++it;
--it;
return (a+b)/2;
}
}
private:
multiset<int> myset;
set<int>::iterator it;
bool isodd;
};
再看看别人的高大上代码
class MedianFinder {
public:
priority_queue<int> loHalf, upHalf;
// Adds a number into the data structure.
void addNum(int num) {
if(loHalf.empty() || num < loHalf.top()) loHalf.push(num);
else upHalf.push(-num);
if(loHalf.size() > 1 + upHalf.size()) {
upHalf.push(-loHalf.top());
loHalf.pop();
}
else if(upHalf.size() > 1 + loHalf.size()) {
loHalf.push(-upHalf.top());
upHalf.pop();
}
}
// Returns the median of current data stream
double findMedian() {
if(loHalf.size() > upHalf.size()) return loHalf.top();
else if(upHalf.size() > loHalf.size()) return -upHalf.top();
else return (loHalf.top() - upHalf.top())/2.0;
}
};
这个方法是把这组数分成两部分lowhalf和uphalf,每次插入后调整这两部分的元素个数,使他们元素个数差不超过1,这样在找中位数时就能根据奇偶和两部分的大小来得出