LeetCode hot 100—数据流的中位数

题目

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

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

实现 MedianFinder 类:

  • MedianFinder() 初始化 MedianFinder 对象。

  • void addNum(int num) 将数据流中的整数 num 添加到数据结构中。

  • double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

示例

示例 1:

输入
["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
[[], [1], [2], [], [3], []]
输出
[null, null, null, 1.5, null, 2.0]

解释
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1);    // arr = [1]
medianFinder.addNum(2);    // arr = [1, 2]
medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2)
medianFinder.addNum(3);    // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0

分析

为了高效地维护数据流中的中位数,可以使用两个堆(最大堆和最小堆)来分别保存较小的一半元素和较大的一半元素。最大堆的堆顶是较小部分的最大值,最小堆的堆顶是较大部分的最小值,这样可以在 O (\log n) 的时间内完成插入和中位数查询操作。

代码解释

数据结构

maxHeap:使用最大堆保存较小的一半元素,堆顶是这部分的最大值。

minHeap:使用最小堆保存较大的一半元素,堆顶是这部分的最小值。

添加元素(addNum

根据当前元素与maxHeap堆顶的大小关系,决定将元素插入到maxHeap(较小部分)还是minHeap(较大部分)。

插入后调整两个堆的大小,确保maxHeap的大小要么等于minHeap,要么比其大 1,以维持平衡。

查找中位数(findMedian

如果总元素个数为奇数,中位数是maxHeap的堆顶(因为maxHeap的大小比minHeap大 1)。

如果总元素个数为偶数,中位数是两个堆堆顶元素的平均值。

时间复杂度:addNum—O(\log n), n 是当前元素个数,findMedian—O(1)

空间复杂度:O(n)

class MedianFinder {
private:
    std::priority_queue maxHeap; // 保存较小的一半元素,最大堆
    std::priority_queue, std::greater> minHeap; // 保存较大的一半元素,最小堆

public:
    MedianFinder() {}
    
    void addNum(int num) {
        // 根据数值大小选择插入的堆
        if (maxHeap.empty() || num <= maxHeap.top()) {
            maxHeap.push(num);
        } else {
            minHeap.push(num);
        }
        
        // 调整堆的大小,保持maxHeap的大小为minHeap的大小或比其大1
        if (maxHeap.size() > minHeap.size() + 1) {
            minHeap.push(maxHeap.top());
            maxHeap.pop();
        } else if (minHeap.size() > maxHeap.size()) {
            maxHeap.push(minHeap.top());
            minHeap.pop();
        }
    }
    
    double findMedian() {
        if ((maxHeap.size() + minHeap.size()) % 2 == 1) {
            // 奇数个元素,中位数是maxHeap的堆顶(因为maxHeap大小多1)
            return static_cast(maxHeap.top());
        } else {
            // 偶数个元素,中位数是两个堆顶的平均值
            return (static_cast(maxHeap.top()) + minHeap.top()) / 2.0;
        }
    }
};

你可能感兴趣的:(leetcode,leetcode,算法,职场和发展,c++,数据结构)