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。先推断堆顶数和新数的大小关系,有以下三种情况:
- 最小堆堆顶小于新插入的数时。说明新插入的数处在全部数的上半部分;
- 最大堆堆顶大于新插入的数时,说明新插入的数处在全部数的下半部分;
- 最小堆堆顶大于新插入的数时,但最大堆堆顶小于新插入的数时,说明新插入的数将处在最小堆堆顶或最大堆堆顶,也就是在中间的位置。
再推断两个堆的大小关系,假设新插入的数属于前两种情况,開始插入目标堆,此时又有两种操作:
- 若目标堆不大于还有一个堆时,将新数插入目标堆;
- 若目标堆大于还有一个堆时,将目标堆的堆顶先移动到还有一个堆。再把新数插入目标堆。
假设新插入的数属于第三种情况。即在中间位置。则插入到大小较小的那个堆就可以。
这样,每次新加进来一个数以后。若两个堆一样大,则中位数是两个堆顶的平均值。否则较大的那个堆的堆顶为中位数。
建立两个堆所用的代码比較长,而使用优先队列来实现则简单很多。
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();
四. 小结
又一次认真学了一下优先队列。受益匪浅。
leetcode笔记:Find Median from Data Stream的更多相关文章
- [LeetCode] 295. Find Median from Data Stream ☆☆☆☆☆(数据流中获取中位数)
295. Find Median from Data Stream&数据流中的中位数 295. Find Median from Data Stream https://leetcode.co ...
- leetcode@ [295]Find Median from Data Stream
https://leetcode.com/problems/find-median-from-data-stream/ Median is the middle value in an ordered ...
- [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 ...
- [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 ...
- LeetCode——295. Find Median from Data Stream
一.题目链接: https://leetcode.com/problems/find-median-from-data-stream 二.题目大意: 给定一段数据流,要求求出数据流中的中位数,其中数据 ...
- 剑指offer 最小的k个数 、 leetcode 215. Kth Largest Element in an Array 、295. Find Median from Data Stream(剑指 数据流中位数)
注意multiset的一个bug: multiset带一个参数的erase函数原型有两种.一是传递一个元素值,如上面例子代码中,这时候删除的是集合中所有值等于输入值的元素,并且返回删除的元素个数:另外 ...
- [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 t ...
- [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 ...
- 【LeetCode】295. Find Median from Data Stream 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 大根堆+小根堆 日期 题目地址:https://le ...
随机推荐
- hadoop的理解
知乎上有个人写的感觉挺好理解的,不知道对不对,先截图存着
- rabbitMQ学习笔记(五) 消息路由
生产者会生产出很多消息 , 但是不同的消费者可能会有不同的需求,只需要接收指定的消息,其他的消息需要被过滤掉. 这时候就可以对消息进行过滤了. 在消费者端设置好需要接收的消息类型. 如果不使用默认的E ...
- CF876A Trip For Meal
CF876A Trip For Meal 题意翻译 小熊维尼非常喜欢蜂蜜! 所以他决定去拜访他的朋友. 小熊有三个最好的朋友:兔子,猫头鹰和小毛驴,每个人都住在自己的房子里. 每对房屋之间都有蜿蜒的小 ...
- Flash的选择
算起来自己接触Flash接近4年了. 最開始的2.0,做button,做动画,做导航. 后来用3.0做动画,做相冊.做毕业设计,做课件. 然后到公司做2.0的动画,模板开发,效果设计. 似乎又回到了原 ...
- hive 配置注意事项及初始化hive 元数据
今天配置hive 犯了一个问题:下载的hive tar.gz 里的conf文件夹仅仅有一个 hive-default.xml.template,于是我就cp 了一份命名为:hive-default. ...
- C++ 浅析 STL 中的 list 容器
list - 擅长插入删除的链表 链表对于数组来说就是相反的存在. 数组本身是没有动态增长能力的(程序中也必须又一次开辟内存来实现), 而链表强悍的就是动态增长和删除的能力. 但对于数组强悍的随机訪问 ...
- Android监听程序自身被卸载
概述: 假设不是一些特殊的情况,我想大家非常少会接触到这个需求.事实上Android的Java部分没有提供对应的接口.这里须要去调用C的代码,也就是说要写JNI了.关于JNI的初识.大家能够去參考我博 ...
- oracle 11g rac 修改VIP、scan VIP、priv IP
11GR2 RAC modify vip,public ip,private ip,scan vip实施步骤1 修改目的 根据业务的需求,需要由原来的临时IP改为生产ip,以下为调整前后对应的I ...
- C++之易混淆知识点四---虚函数与虚继承
C++面向对象中,虚函数与虚继承是两个完全不同的概念. 一.虚函数 C++程序中只要类中含有虚拟函数,编译程序都会为此类生成一个对应的虚拟函数跳转表(vtbl),该虚拟函数跳转表是一个又若干个虚拟函数 ...
- UWP 开发相关
OCR 识别问题 ocr.OcrEngine.availableRecognizerLanguages 如果 length 只有 1,有可能只能识别英文,需要安装中文语言包~