Problem:
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:
- void addNum(int num) – Add a integer number from the data stream to the data structure.
- double findMedian() – Return the median of all elements so far.
For example:
1 2 3 4 5 |
addNum(1) addNum(2) findMedian() = 1.5 addNum(3) findMedian() = 2 |
Idea:
- Min/Max heap
- Balanced binary search tree
Time Complexity:
add(num): O(logn)
findMedian(): O(logn)
Solution1:
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 |
// Author: Huahua // Running Time: 152 ms class MedianFinder { public: /** initialize your data structure here. */ MedianFinder() {} // l_.size() >= r_.size() void addNum(int num) { if (l_.empty() || num <= l_.top()) { l_.push(num); } else { r_.push(num); } // Step 2: Balence left/right 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 static_cast<double>(l_.top()); } else { return (static_cast<double>(l_.top()) + r_.top()) / 2; } } private: priority_queue<int, vector<int>, less<int>> l_; // max-heap priority_queue<int, vector<int>, greater<int>> r_; // min-heap }; |
Solution 2:
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 |
// Author: Huahua // Running time: 172 ms class MedianFinder { public: /** initialize your data structure here. */ MedianFinder(): l_(m_.cend()), r_(m_.cend()) {} // O(logn) 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) { // odd number if (num >= *r_) { l_ = r_; } else { // num < *r_, l_ could be invalidated l_ = --r_; } } else { if (num >= *r_) ++r_; else --l_; } } // O(1) double findMedian() { return (static_cast<double>(*l_) + *r_) / 2; } private: multiset<int> m_; multiset<int>::const_iterator l_; // current left median multiset<int>::const_iterator r_; // current right median }; |
Related Problems