剑指 Offer 41. 数据流中的中位数

发布时间 2023-04-08 23:58:42作者: lxy_cn

题目链接:剑指 Offer 41. 数据流中的中位数

方法一:插入排序

解题思路

每次添加一个数字时,通过插入排序添加,需要返回中位数时,根据元素个数进行返回。

代码

class MedianFinder {
private:
    vector<int> nums;
public:
    /** initialize your data structure here. */
    MedianFinder() {
    }
    
    void addNum(int num) {
        nums.push_back(num);
        for (int i = nums.size() - 1; i > 0; i -- ) {
            if (nums[i] < nums[i - 1]) swap(nums[i], nums[i - 1]);
            else break;
        }
    }
    
    double findMedian() {
        int cnt = nums.size();
        if (cnt == 0) return NULL;
        int mid = cnt / 2;
        if (cnt % 2 == 0) return (nums[mid] + nums[mid - 1]) / 2.0;
        else return nums[mid];
    }
};

复杂度分析

执行用时:1360 ms, 在所有 C++ 提交中击败了5.04%的用户
内存消耗:40.7 MB, 在所有 C++ 提交中击败了59.16%的用户
通过测试用例:18 / 18
\(addNum()\):时间复杂度为\(O(n)\),空间复杂度为\(O(1)\)
\(findMedian()\):时间复杂度为\(O(1)\),空间复杂度为\(O(1)\)

方法二:优先队列

解题思路

通过优先队列维护两个数组\(queMin\)\(queMax\)\(queMin\)保存数据流中较小的一部分数(从大到小),\(queMax\)保存数据流中较大的一部分数(从小到大),\(queMax.size() - queMin.size() == 0 || 1\),则样\(queMin.top()\)\(queMax.top()\)就是数据流中间的\(1\)个数中间的\(2\)个数

代码

class MedianFinder {
private:
    priority_queue<int, vector<int>, less<int>> queMin;
    priority_queue<int, vector<int>, greater<int>> queMax;
public:
    /** initialize your data structure here. */
    MedianFinder() {

    }
    
    void addNum(int num) {
        if (queMin.empty() || num < queMin.top()) {
            queMin.push(num);
            if (queMax.size() + 1 < queMin.size()) { // queMax元素数量少于queMin元素数量超过1个
                queMax.push(queMin.top()); // 将queMin的最大值转移到queMax中,保持平衡
                queMin.pop();
            }
        } else {
            queMax.push(num);
            if (queMax.size() > queMin.size()) { // queMax元素数量超过queMin元素数量
                queMin.push(queMax.top()); // 将queMax的最小值转移到queMin中,保持平衡
                queMax.pop();
            }
        }
    }
    
    double findMedian() {
        if (queMin.size() > queMax.size()) return queMin.top();
        return (queMin.top() + queMax.top()) / 2.0;
    }
};

复杂度分析

执行用时:84 ms, 在所有 C++ 提交中击败了93.98%的用户
内存消耗:40.7 MB, 在所有 C++ 提交中击败了33.52%的用户
通过测试用例:18 / 18
\(addNum()\):时间复杂度为\(O(logn)\),空间复杂度为\(O(1)\)
\(findMedian()\):时间复杂度为\(O(1)\),空间复杂度为\(O(1)\)