题目描述:
实现数据结构,插入数据和查找中位数。
思路:
- vector + sort, O ( n 2 n^2 n2)
- 维护一个最大堆和一个最小堆,两者元素个数最大相差1,中位数即为最小堆堆顶元素或最大堆最小堆堆顶元素平均值。用优先队列实现。 (n log(n)) 。
- 用二叉搜索树维护数组,两个指针指向中位数元素。用multi_set实现。时间复杂度同上。
代码:
堆:
class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder() {}
void addNum(int num) {
if (L_.empty() || num < L_.top()) L_.push(num);
else R_.push(num);
if (L_.size() < R_.size()) {
L_.push(R_.top());
R_.pop();
}else if (L_.size() - R_.size() == 2) {
R_.push(L_.top());
L_.pop();
}
}
double findMedian() {
if (L_.size() == R_.size())
return (L_.top() + R_.top()) * 1.0 / 2;
else return L_.top();
}
private:
priority_queue<int, vector<int>, less<int>> L_; // max_heap
priority_queue<int, vector<int>, greater<int>> R_; // min_heap
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/
二叉搜索树:
class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder(): l_(m_.cend()), r_(m_.cend()) {}
void addNum(int num) {
if (m_.empty()) {
l_ = r_ = m_.insert(num);
return;
}
m_.insert(num);
const size_t n = m_.size();
if (n & 1) { // 奇数
if (num >= *r_) l_ = r_;
else l_ = --r_;
}else {
if (num >= *r_) ++r_;
else --l_;
}
}
double findMedian() {
return (*l_ + *r_) * 1.0 / 2;
}
private:
multiset<int> m_;
multiset<int>::const_iterator l_;
multiset<int>::const_iterator r_;
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/