题目: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:
add(1)
add(2)
findMedian() -> 1.5
add(3)
findMedian() -> 2
题意:
给你一堆数,找出这些数的中位数,如果是偶数个数字,那么中位数就是最中间两个数字的平均值。实现两个函数,一个是往数据结构中加入某个整数,一个函数是求出当前这堆数据流的平均值。
思路:
最简单的思维方式是,向一个容器里面加入数字,然后进行排序,时间复杂度是O(n(log(n)),然后花O(1)的时间找出中位数。
这里可以考虑使用堆这种数据结构,使用一个最大堆,使用一个最小堆,如果保证最大堆中的元素都小于等于最小堆的元素,并且如果两者元素相同,那么中位数就是最大堆的堆顶元素和最小堆的堆顶元素的平均值。数据结构在加入数字的时候保证两点:
- 最大堆的元素都小于等于最小堆的元素。
- 两者元素个数相差不超过1。
具体实现的话,使用C++中的优先级队列,因为优先级队列就是使用的堆得操作。priority_queue的默认使用的是最大堆,即堆顶元素是最大值。最小堆需要我们加入模板参数,priority_queue
class MedianFinder {
public:
MedianFinder() {
num_small = 0;
num_big = 0;
}
// Adds a number into the data structure.
void addNum(int num) {
if(num_small == num_big) {
if(num_small == 0) {
small.push(num);
}
else {
if(big.top() < num) {
int temp = big.top();
big.pop();
small.push(temp);
big.push(num);
}
else small.push(num);
}
num_small++;
}
else {
if(small.top() > num) {
int temp = small.top();
small.pop();
big.push(temp);
small.push(num);
}
else big.push(num);
num_big++;
}
}
// Returns the median of current data stream
double findMedian() {
if(num_small == 0)return 0;
else if(num_small > num_big)return small.top();
else return (small.top() + big.top())/2.0;
}
private:
priority_queue<int> small;
priority_queue<int, std::vector<int>, std::greater<int>> big;
int num_small;
int num_big;
};
// Your MedianFinder object will be instantiated and called as such:
// MedianFinder mf;
// mf.addNum(1);
// mf.findMedian();