【LeetCode】295. 数据流的中位数 结题报告 (C++)

原题地址:https://leetcode-cn.com/problems/find-median-from-data-stream/

题目描述:

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

例如,

[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
进阶:

如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?

解题方案:

设计题型。这里使用了C++STL中的upper_bound()函数。

upper_bound(a.begin(),a.end(),x)返回的是迭代器,upper_bound(a+i,a+j,x)-a返回的是第一个大于x的数的坐标。

在这里算是在指定位置插入元素。upper_bound()和insert()函数组合使用。

代码:

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值即可。 

代码:

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/qq_32805671/article/details/84926921
今日推荐