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

二. 题目分析

题目大意是,在一串输入的数据流中寻找中位数。所谓中位数,就是指有序整数列表的中间值。如果列表的长度为偶数,此时没有中间值。则其中位数就是两个中间值的平均值。

例如:

[2,3,4], 中位数是 3

[2,3], 中位数是 (2 + 3) / 2 = 2.5

设计一种数据结构,支持下面两种操作:

void addNum(int num) // 该函数从数据流向数据结构加入一个整数

double findMedian() // 返回截至目前所有元素的中位数

该题的经典做法是,维护一个最大堆和一个最小堆。最大堆存的是截至目前为止较小的那一半数,最小堆存放的是截至目前为止较大的那一半数,这样中位数只有可能是堆顶或者两个堆顶所对应两个数的平均值。

维护两个堆的技巧在于判断堆顶端的数和新插入的数的大小关系,另外,由于两个堆平分了所有数,因此还需要考虑两者的大小关系。这里我们规定两个堆的大小之差不超过1。先判断堆顶数和新数的大小关系,有以下三种情况:

  1. 最小堆堆顶小于新插入的数时,说明新插入的数处在所有数的上半部分;
  2. 最大堆堆顶大于新插入的数时,说明新插入的数处在所有数的下半部分;
  3. 最小堆堆顶大于新插入的数时,但最大堆堆顶小于新插入的数时,说明新插入的数将处在最小堆堆顶或最大堆堆顶,也就是在中间的位置。

再判断两个堆的大小关系,如果新插入的数属于前两种情况,开始插入目标堆,此时又有两种操作:

  1. 若目标堆不大于另一个堆时,将新数插入目标堆;
  2. 若目标堆大于另一个堆时,将目标堆的堆顶先移动到另一个堆,再把新数插入目标堆。

如果新插入的数属于第三种情况,即在中间位置,则插入到大小较小的那个堆即可。这样,每次新加进来一个数以后,若两个堆一样大,则中位数是两个堆顶的平均值,否则较大的那个堆的堆顶为中位数。

建立两个堆所用的代码比较长,而使用优先队列来实现则简单许多。

priority_queue:优先队列,是一个拥有权值概念的单向队列,在这个队列中,所有元素是按优先级排列的。优先队列有两种,一种是最大优先队列;一种是最小优先队列;每次取自队列的第一个元素分别是优先级最大和优先级最小的元素。

实际使用时,加入头文件:"queue.h", "functional.h"

其中”functional.h”定义了优先级。(若要自己定义优先级可以不加)关于优先队列的使用可参照:

http://www.cnblogs.com/summerRQ/articles/2470130.html

http://blog.csdn.net/zhang20072844/article/details/10286997

三. 示例代码

class MedianFinder
{
private:
    priority_queue<int,std::vector<int>, std::greater<int>> q1; // 数据越小,优先级越高
    priority_queue<int> q2; // 数据越大,优先级越高

public:

    void addNum(int num)
    {
        if(q2.empty())
        {
            q2.push(num);
            return;
        }
        if(num <= q2.top())
        {
            if(q2.size() <= q1.size()) q2.push(num);
            else
            {
                q1.push(q2.top());
                q2.pop();
                q2.push(num);
            }
        }
        else
        {
            if(q2.size() <= q1.size())
            {
                if(num <= q1.top()) q2.push(num);
                else
                {
                    q2.push(q1.top());
                    q1.pop();
                    q1.push(num);
                }
            }
            else
            {
                q1.push(num);
            }
        }
    }

    double findMedian()
    {
        if(q1.size() == q2.size()) return (q1.top() + q2.top()) / 2.0;
        return double(q2.top());
    }
};

// Your MedianFinder object will be instantiated and called as such:
// MedianFinder mf;
// mf.addNum(1);
// mf.findMedian();

四. 小结

重新认真学了一下优先队列,受益匪浅。

时间: 2025-01-31 07:46:57

leetcode笔记:Find Median from Data Stream的相关文章

LeetCode之Find Median from Data Stream

1.题目描述 翻译过来就是对输入的数字找出其中位数. 2.解题思路 一开始,我想着这是动态输入,所以必须放弃数组这些静态的数据结构.首先想到了平衡二叉树,然而太麻烦了.后面又想到了大顶堆以及小顶堆,但是不知如何运用,就上这道题discuss瞅了瞅.结果发现了一种double heap解法,十分带感,总体思路就是比中位数大的数字放一边(大数堆),小的放另一边(小数堆).然后也接触了并且运用一种新的队列用法——优先队列.插入数字过程中,始终保持大数堆大小大于等于小数堆,以便最后输出中位数.代码如下:

LeetCode——295. Find Median from Data Stream

一.题目链接: https://leetcode.com/problems/find-median-from-data-stream 二.题目大意: 给定一段数据流,要求求出数据流中的中位数,其中数据流是动态变化的.如果数据流中的数字个数是奇数的话,则中位数是中间位置的数字:如果数据流中的数字是偶数的话,则中位数是排序好的数据流中的中间两个数的的平均值. 三.题解: 如果数据流是静态不变的话,此时问题是比较好求解的.但是数据流是动态变化的,所以数据流中每次进入一个新的数字时,都要保证能够高效的找

[LeetCode] Find Median from Data Stream

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

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

数据结构与算法(1)支线任务8——Find Median from Data Stream

题目如下:(https://leetcode.com/problems/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] 

[email&#160;protected] [295]Find Median from Data Stream

https://leetcode.com/problems/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 m

Find Median from Data Stream 295

题目链接:https://leetcode.com/problems/find-median-from-data-stream/ 题目描述: 设计一个类,包含两种操作 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. 操作 addNum向数列中添

支线任务8-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 Des

Find Median from Data Stream

常规方法 超时 class MedianFinder { vector<int> coll; public: MedianFinder(){ } void heapfu(vector<int>& coll,int idx,int max){ int left=2*idx+1,right=2*idx+2; int largest=idx; if(left<max&&coll[left]>coll[idx]) largest=left; if(rig