[C++] LeetCode 295. 数据流的中位数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lv1224/article/details/82222719

题目

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:
void addNum(int num)- 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。

示例:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

进阶:
如果数据流中所有整数都在 0100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0100 范围内,你将如何优化你的算法?

题解

这里要求中位数可以考虑用一个有序的数组来保存输入的数据,然后对于列表个数为偶数,则直接取出中间两个求均值即可,如果是奇数则取中间值即可。
代码:

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {

    }

    void addNum(int num) {
        auto it=upper_bound(nums.begin(),nums.end(),num);
        nums.insert(it,num);
    }

    double findMedian() {
        int n=nums.size();
        if(n%2==0) return 1.0*(nums[n/2-1]+nums[n/2])/2;
        else return nums[n/2];
    }
    vector<int> nums;
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

方法二

对于一个列表取中位数的时候我们只需要知道中间的数即可,至于整个数组是否有序并不重要,而用一个数组来保存列表,则需要对所有的数据排序,时间复杂度较高。既然不需要所有的数据有序,只需要中间的值,很自然想到把列表分成两半,分别用两个数据结构来保存,比如[1,3,4,5,6,7],对于这个列表,可以存为[1,3,4][5,6,7],那么只需要中间的值就可以得出中位数了。可以考虑采用优先级队列,priority_queue,左侧为数字越大优先级越高,右侧为数字越小优先级越高。那么取出两个优先级的top值即可。
注: 优先级队列中,less表示数字越大优先级越高,greater表示数字越小优先级越高。

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {

    }

    void addNum(int num) {
        left.push(num);
        if(left.size()-right.size()>1) {
            right.push(left.top());
            left.pop();
        }
        if(right.size()>0 && left.top()>right.top()){
            int tmp=left.top();
            left.pop();
            left.push(right.top());
            right.pop();
            right.push(tmp);
        }
    }

    double findMedian() {
        if(left.size()==right.size()) return 1.0*(left.top()+right.top())/2;
        else return left.top();
    }
    priority_queue<int, vector<int>,greater<int>> right;
    priority_queue<int, vector<int>,less<int>> left;
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

猜你喜欢

转载自blog.csdn.net/lv1224/article/details/82222719
今日推荐