295. Find Median from Data Stream

51 篇文章 0 订阅
Description

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

For example,
[2,3,4], the median is 3

[2,3], the median is (2 + 3) / 2 = 2.5

Design a data structure that supports the following two operations:

void addNum(int num) - Add a integer number from the data stream to the data structure.
double findMedian() - Return the median of all elements so far.

Example:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

Follow up:

If all integer numbers from the stream are between 0 and 100, how would you optimize it?
If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?

Problem URL


Solution

设计一个数据结构,能够存贮一系列的数,并且快速找到它们的中位数。

Using two priority queue(heap) to solve this problem. left is a max heap which stores left part, and right is a min heap which stores right part. When a new number comes in, store to right first then store right.poll() to left. If right.size() < left.size(), poll() left to right to make sure median is in right part when number of numbers is odd.

Code
class MedianFinder {
    Queue<Integer> left;
    Queue<Integer> right;
    /** initialize your data structure here. */
    public MedianFinder() {
        left = new PriorityQueue<>();
        right = new PriorityQueue<>(Collections.reverseOrder());
    }
    
    public void addNum(int num) {
        right.offer(num);
        left.offer(right.poll());
        if (right.size() < left.size()){
            right.offer(left.poll());
        }
    }
    
    public double findMedian() {
        if (right.size() == left.size()){
            return (right.peek() + left.peek()) / 2.0;
        }
        else{
            return right.peek();
        }
    }
}

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

Time Complexity: O()
Space Complexity: O()


Review
要找出数据流的中位数,可以使用两个优先队列(堆)来实现。一个小顶堆存储较大的一半数据,一个大顶堆存储较小的一半数据。 具体步骤如下: 1. 初始化两个堆,一个小顶堆 `minHeap` 和一个大顶堆 `maxHeap`。 2. 遍历数据流中的每个元素: - 如果 `minHeap` 和 `maxHeap` 的大小相等,将元素插入到 `maxHeap` 中。 - 如果 `minHeap` 的大小大于 `maxHeap`,将元素插入到 `minHeap` 中。 - 如果插入元素后,`minHeap` 的堆顶元素大于 `maxHeap` 的堆顶元素,则交换两个堆顶元素。 3. 如果两个堆的大小之和是偶数,中位数就是两个堆顶元素的平均值;如果是奇数,中位数就是 `minHeap` 的堆顶元素。 下面是使用 C++ 实现的代码示例: ```cpp #include <iostream> #include <queue> #include <vector> class MedianFinder { public: void addNum(int num) { if (minHeap.empty() || num > minHeap.top()) { minHeap.push(num); } else { maxHeap.push(num); } if (minHeap.size() > maxHeap.size() + 1) { maxHeap.push(minHeap.top()); minHeap.pop(); } else if (maxHeap.size() > minHeap.size()) { minHeap.push(maxHeap.top()); maxHeap.pop(); } } double findMedian() { if (minHeap.size() == maxHeap.size()) { return (minHeap.top() + maxHeap.top()) / 2.0; } else { return minHeap.top(); } } private: std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap; std::priority_queue<int, std::vector<int>, std::less<int>> maxHeap; }; int main() { MedianFinder finder; finder.addNum(1); finder.addNum(2); std::cout << finder.findMedian() << std::endl; // 输出 1.5 finder.addNum(3); std::cout << finder.findMedian() << std::endl; // 输出 2 return 0; } ``` 这段代码创建了一个 `MedianFinder` 类,通过 `addNum` 方法添加数据,然后通过 `findMedian` 方法获取中位数。在示例中,数据流为 1、2、3,所以中位数依次为 1.5 和 2。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值