[LeetCode] Find Median from Data Stream 找出数据流的中位数

简介:

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.

Examples:

[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.

For example:

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

Credits:
Special thanks to @Louis1992 for adding this problem and creating all test cases.

这道题给我们一个数据流,让我们找出中位数,由于数据流中的数据并不是有序的,所以我们首先应该想个方法让其有序。如果我们用vector来保存数据流的话,每进来一个新数据都要给数组排序,很不高效。所以之后想到用multiset这个数据结构,是有序保存数据的,但是它不能用下标直接访问元素,找中位数也不高效。这里用到的解法十分巧妙,我们使用大小堆来解决问题,其中大堆保存右半段较大的数字,小堆保存左半段较小的数组。这样整个数组就被中间分为两段了,由于堆的保存方式是由大到小,我们希望大堆里面的数据是从小到大,这样取第一个来计算中位数方便。我们用到一个小技巧,就是存到大堆里的数先取反再存,这样由大到小存下来的顺序就是实际上我们想要的从小到大的顺序。当大堆和小堆中的数字一样多时,我们取出大堆小堆的首元素求平均值,当小堆元素多时,取小堆首元素为中位数,参见代码如下:

解法一:

class MedianFinder {
public:

    // Adds a number into the data structure.
    void addNum(int num) {
        small.push(num);
        large.push(-small.top());
        small.pop();
        if (small.size() < large.size()) {
            small.push(-large.top());
            large.pop();
        }
    }

    // Returns the median of current data stream
    double findMedian() {
        return small.size() > large.size() ? small.top() : 0.5 *(small.top() - large.top());
    }

private:
    priority_queue<long> small, large;
};

上述方法是用priority_queue来实现堆功能的,下面我们还可用multiset来实现堆,参见代码如下:

解法二:

class MedianFinder {
public:
// Adds a number into the data structure.
    void addNum(int num) {
        small.insert(num);
        large.insert(-*small.begin());
        small.erase(small.begin());
        if (small.size() < large.size()) {
            small.insert(-*large.begin());
            large.erase(large.begin());
        }
    }

    // Returns the median of current data stream
    double findMedian() {
        return small.size() > large.size() ? *small.begin() : 0.5 * (*small.begin() - *large.begin());
    }

private:
    multiset<long> small, large;
};

本文转自博客园Grandyang的博客,原文链接:找出数据流的中位数[LeetCode] Find Median from Data Stream ,如需转载请自行联系原博主。

相关文章
|
10月前
|
算法 Java
LeetCode寻找两个有序数组的中位数打败100%人
LeetCode寻找两个有序数组的中位数打败100%人
79 0
|
10月前
|
算法
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
82 0
|
10月前
|
算法
leetcode代码记录(寻找两个正序数组的中位数
leetcode代码记录(寻找两个正序数组的中位数
67 2
|
9月前
|
SQL 算法 数据挖掘
LeetCode 第四题:寻找两个正序数组的中位数 【4/1000 】【python + go】
LeetCode 第四题:寻找两个正序数组的中位数 【4/1000 】【python + go】
|
10月前
|
算法
【力扣】4. 寻找两个正序数组的中位数
【力扣】4. 寻找两个正序数组的中位数
|
10月前
|
存储 算法
《LeetCode 热题 HOT 100》——寻找两个正序数组的中位数
《LeetCode 热题 HOT 100》——寻找两个正序数组的中位数
|
10月前
|
存储 算法 Go
LeetCode第四题: 寻找两个正序数组的中位数
给定两个大小分别为m和n的正序(从小到大)数组nums1和nums2。请你找出并返回这两个正序数组的中位数。
|
10月前
|
算法 测试技术 C#
【map】【滑动窗口】【优先队列】LeetCode480滑动窗口中位数
【map】【滑动窗口】【优先队列】LeetCode480滑动窗口中位数
|
10月前
leetcode-4:寻找两个正序数组的中位数
leetcode-4:寻找两个正序数组的中位数
49 0
|
10月前
|
算法 安全 C#
Leetcode算法系列| 4. 寻找两个正序数组的中位数
Leetcode算法系列| 4. 寻找两个正序数组的中位数