1、二分按顺序插入
class MedianFinder {
private:
vector<int> v;
double mid = 0;;
int size = 0;
public:
MedianFinder() {
}
void addNum(int num) {
v.insert(lower_bound(v.begin(), v.end(), num), num);
size++;
if (size % 2)
mid = v[size / 2];
else
mid = (double)v[size / 2] / 2 + (double)v[size / 2 - 1] / 2;
}
double findMedian() {
return mid;
}
};
超时
2、用两个堆
class MedianFinder {
private:
priority_queue<int> q1;//大顶堆
priority_queue<int, vector<int>, greater<int>> q2;//小顶堆
int size1 = 0, size2 = 0;
public:
MedianFinder() {
}
void addNum(int num) {
if (size1 == 0) {
q1.push(num);
size1++;
return;
}
if (size2 == 0) {
if (num >= q1.top())
q2.push(num);
else {
q2.push(q1.top());
q1.pop();
q1.push(num);
}
size2++;
return;
}
if (num > q2.top()) {
if (size1 == size2) {
q1.push(q2.top());
q2.pop();
q2.push(num);
size1++;
}
else {
q2.push(num);
size2++;
}
}
else if (num > q1.top()) {
if (size1 == size2) {
q1.push(num);
size1++;
}
else {
q2.push(num);
size2++;
}
}
else if (size1 > size2) {
q2.push(q1.top());
q1.pop();
q1.push(num);
size2++;
}
else {
q1.push(num);
size1++;
}
}
double findMedian() {
if (size1 > size2)
return q1.top();
else
return ((double)q1.top() + (double)q2.top()) / 2;
}
};
好吧,还是堆比较快,相当于从两边夹。
3、类似方法一,数据结构用multiset
class MedianFinder {
multiset<int> nums;
multiset<int>::iterator left, right;
public:
MedianFinder() : left(nums.end()), right(nums.end()) {}
void addNum(int num) {
const size_t n = nums.size();
nums.insert(num);
if (!n) {
left = right = nums.begin();
} else if (n & 1) {
if (num < *left) {
left--;
} else {
right++;
}
} else {
if (num > *left && num < *right) {
left++;
right--;
} else if (num >= *right) {
left++;
} else {
right--;
left = right;
}
}
}
double findMedian() {
return (*left + *right) / 2.0;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/find-median-from-data-stream/solution/shu-ju-liu-de-zhong-wei-shu-by-leetcode-ktkst/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
感觉其实和方法一比较相似,就是用了multiset。
multiset是多重集,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,而且序列中可以存在重复的数。