一.题目链接:

  https://leetcode.com/problems/find-median-from-data-stream

二.题目大意:

  给定一段数据流,要求求出数据流中的中位数,其中数据流是动态变化的。如果数据流中的数字个数是奇数的话,则中位数是中间位置的数字;如果数据流中的数字是偶数的话,则中位数是排序好的数据流中的中间两个数的的平均值。

三.题解:

  如果数据流是静态不变的话,此时问题是比较好求解的。但是数据流是动态变化的,所以数据流中每次进入一个新的数字时,都要保证能够高效的找到数据流的中位数。我们可以这么考虑:如果把数据流中的数字分为个数相同的两部分的话(假设为A和B,其中A中的数字全部小于B中的数字),那么我们所求的中位数,实质就是A中的最大值和B中的最小值的平均值。因此,我们可以用两个堆来表示这个过程,其中大顶堆maxH存储的是数据流中的数值较小的数字,而小顶堆minH存储的是数据六中数值较大的数字,且maxH中的数字全部小于minH中的数字。并且堆可以快速的找出其中的最值,所以可以快速找得到minH中的最小值和maxH中的最大值,从而求出中位数。代码如下:

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#include<stack>
#define MAX_NUM 100
using namespace std;
class MedianFinder {
public:
/** initialize your data structure here. */
priority_queue<int,vector<int>,less<int>> maxH;//定义大顶堆,用于存储较小的数据部分
priority_queue<int,vector<int>,greater<int>> minH;//定义小顶堆,用于存储较大的数据部分
MedianFinder() { } void addNum(int num) {
maxH.push(num);
int tmp = maxH.top();
maxH.pop();
minH.push(tmp);//保证小顶堆中的数据大于大顶堆中的数据
if(minH.size() > maxH.size())
{
int tmp = minH.top();
minH.pop();
maxH.push(tmp);//保证大顶堆中的数据小于小顶堆中的数据
} } double findMedian() {
if(minH.size() == maxH.size())//如果两个堆的大小相同,则返回它们最值的平均值
return (minH.top() + maxH.top()) / 2.0;
return minH.size() > maxH.size() ? minH.top() : maxH.top();//如果两个堆的大小不相同,返回数字个数多的堆的最值
}
}; /**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/ int main()
{
MedianFinder test = MedianFinder();
test.addNum(1);
test.addNum(2);
test.addNum(3);
test.addNum(4);
test.addNum(5);
cout<<test.findMedian()<<endl; }

每次从数据流中找出中位数的时间为O(1),调整两个堆的时间为O(logN),对于含有n个数字的数据流,总的时间复杂度为O(NlogN),空间复杂度为O(N)。

此外,有几个点需要注意下:

1.代码中使用了priority_queue即优先队列来实现堆,因为优先队列获取优先级最高的值所需时间为O(1),调整的过程为O(logN),与堆的操作时间类似,能较好的模拟堆。

2.通常情况下,堆默认的优先级最高的值是指的最大值,也可以是最小值,不过需要显式的说明(见本例中优先队列的定义)。

3.要保证最小堆中存储的始终是较大的数值,而大顶堆中存储的是较小的数值。所以才会有addNum中的那些操作。

LeetCode——295. Find Median from Data Stream的更多相关文章

  1. [LeetCode] 295. Find Median from Data Stream ☆☆☆☆☆(数据流中获取中位数)

    295. Find Median from Data Stream&数据流中的中位数 295. Find Median from Data Stream https://leetcode.co ...

  2. leetcode@ [295]Find Median from Data Stream

    https://leetcode.com/problems/find-median-from-data-stream/ Median is the middle value in an ordered ...

  3. [LeetCode] 295. 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 ...

  4. [leetcode]295. 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 ...

  5. 剑指offer 最小的k个数 、 leetcode 215. Kth Largest Element in an Array 、295. Find Median from Data Stream(剑指 数据流中位数)

    注意multiset的一个bug: multiset带一个参数的erase函数原型有两种.一是传递一个元素值,如上面例子代码中,这时候删除的是集合中所有值等于输入值的元素,并且返回删除的元素个数:另外 ...

  6. 【LeetCode】295. Find Median from Data Stream 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 大根堆+小根堆 日期 题目地址:https://le ...

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

  8. [LC] 295. 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 ...

  9. 295 Find Median from Data Stream 数据流的中位数

    中位数是排序后列表的中间值.如果列表的大小是偶数,则没有中间值,此时中位数是中间两个数的平均值.示例:[2,3,4] , 中位数是 3[2,3], 中位数是 (2 + 3) / 2 = 2.5设计一个 ...

随机推荐

  1. 【原创】Proxmark3系列教程1——PM3用法

    1 PM3介绍 proxmark3是一款开源的RFID安全研究平台黑色按钮从图中我们可以看到左上方有一颗黑色按钮,这个按钮就是Proxmark3的功能键,主要用于启动嗅探模式以及停止进程功能,其中内置 ...

  2. Tmux会话-基本操作及原理

    一.Tmux命令介绍: Tmux (“Terminal Multiplexer”的简称), 是一款优秀的终端复用软件,类似 GNU screen,但比screen更出色. tmux来自于OpenBSD ...

  3. swiper遇到的问题

    <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

  4. iOS代码块block使用

    代码块的本质是和其他的变量类似,不同的是,代码块存储的数据是一个函数体.使用代码块,你可以像调用其他标准函数一样的调用,可以传入参数,并得到返回值.     脱字符是代码块的语法标记.下图表示代码块的 ...

  5. 嵌入式C语言编译器

    GCC与gcc: 初识编译器: 扩展问题: 如何理解“多语言混合开发”? 参考: 狄泰软件学院唐佐林视频教程

  6. 【leetcode】476. Number Complement

    problem 476. Number Complement solution1: class Solution { public: int findComplement(int num) { //正 ...

  7. EEG 睡眠 节律 代码

    a1=load('EEG01.txt');[c,r]=size(a1);z=10;%等于几,绘图起点从几开始s=256*z;%绘图起点;还有,这里的256是采样率d=floor(c/256);cn=d ...

  8. 关于OSI

    OSI模型,即开放式通信系统互联参考模型(Open System Interconnection,OSI/RM,Open Systems Interconnection Reference Model ...

  9. vue中使用video插件vue-video-player

    一.安装插件 npm install vue-video-player --save 二.配置插件 在main.js中全局配置插件 import VideoPlayer from 'vue-video ...

  10. js···元素的属性

    Div.attributes 是所有标签属性构成的数据集合 Div.classList 是所有class名构成的数组集合 在classList的原型链上看以看到add()和remove(). clie ...