问题描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

例如,

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

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

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
示例 1: 输入:
["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]
[[],[1],[2],[],[3],[]]
输出:[null,null,null,1.50000,null,2.00000]
示例 2: 输入:
["MedianFinder","addNum","findMedian","addNum","findMedian"]
[[],[2],[],[3],[]]
输出:[null,null,2.00000,null,2.50000]
  限制: 最多会对 addNum、findMedia进行 50000 次调用。

问题分析

使用一个大顶堆和一个小顶堆,其中小顶堆中的数据永远大于大顶堆中的数据(这样左端大顶堆的堆顶就是左半部分最大值,右端小顶堆的堆顶就是右半部分最小值),并且使得小顶堆中元素个数要么等于大顶堆中元素个数,要么比大顶堆中元素个数少一个,第一个情形返回两个堆顶的平均值,第二种情况返回大顶堆的堆顶元素即可。

代码

class MedianFinder {
private:
priority_queue<int,vector<int>,greater<int>> rightq;//小顶堆
priority_queue<int,vector<int>,less<int>> leftq;//大顶堆
public:
/** initialize your data structure here. */
MedianFinder() { } void addNum(int num) {
//此时要使leftq.size()==rightq.size()+1,将新元素放入小顶堆后,取出堆顶元素放入大顶堆
if(leftq.size() == rightq.size())
{
rightq.push(num);
leftq.push(rightq.top());
rightq.pop();
}
//此时leftq.size()==rightq.size()+1,要使两个堆元素个数相等,先把新元素放入大顶堆找出新的大顶堆最大元素放入小顶堆
else{
leftq.push(num);
rightq.push(leftq.top());
leftq.pop();
}
} double findMedian() {
if(leftq.size() == rightq.size())
{
return (leftq.top()+rightq.top())/2.0;
}
else{
return leftq.top();
}
}
}; /**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/

结果

执行用时 :280 ms, 在所有 C++ 提交中击败了46.21%的用户
内存消耗 :41.6 MB, 在所有 C++ 提交中击败了100.00%的用户

注意priority_queue使用基本数据类型时,只需要传入数据类型,默认是大顶堆。

《剑指offer》面试题41. 数据流中的中位数的更多相关文章

  1. 剑指offer(63)数据流中的中位数

    题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值.我们 ...

  2. 【剑指Offer】63、数据流中的中位数

      题目描述:   如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平 ...

  3. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

  4. 剑指offer系列37----数据流中的中位数

    [题目]如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值, * 那么中位数就是所有数值排序之后位于中间的数值. package com.exe8.offer; import java.uti ...

  5. 剑指offer 面试题64 数据流的中位数

    struct cmp { bool operator()(double a, double b) { return a > b; } }; class Solution { public: vo ...

  6. 剑指Offer:面试题29——数组中出现次数超过一半的数字(java实现)

    PS:在前几天的面试中,被问到了这个题.然而当时只能用最低效的方法来解. 问题描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2, ...

  7. 剑指offer 面试题 删除链表中重复的节点

    题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...

  8. 剑指offer 面试题56. 数组中只出现一次的两个数字

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 方法1:用set记录出现过的数字 class Solution { public: void F ...

  9. 剑指 Offer 41. 数据流中的中位数 + 堆 + 优先队列

    剑指 Offer 41. 数据流中的中位数 Offer_41 题目详情 题解分析 本题使用大根堆和小根堆来解决这个寻找中位数和插入中位数的问题. 其实本题最直接的方法是先对数组进行排序,然后取中位数. ...

随机推荐

  1. CF729A Interview with Oleg 题解

    Content 给出一个长度为 \(n\) 字符串 \(s\),请将开头为 \(\texttt{ogo}\),后面带若干个 \(\texttt{go}\) 的子串替换成 \(\texttt{***}\ ...

  2. 『学了就忘』Linux系统定时任务 — 89、任务调度工具anacron

    目录 1.任务调度工具anacron介绍 2.新旧版本Linux中anacron工具的区别 3./etc/cron.{daily,weekly,monthly}目录说明 4.anacron命令 5./ ...

  3. Go语言核心36讲(Go语言实战与应用二十七)--学习笔记

    49 | 程序性能分析基础(下) 在上一篇文章中,我们围绕着"怎样让程序对 CPU 概要信息进行采样"这一问题进行了探讨,今天,我们再来一起看看它的拓展问题. 知识扩展 问题 1: ...

  4. Nginx 编译数格式化输出

    printf "%s\n" `nginx -V 2>&1` nginx -V 2>&1 | sed 's/ /\n/g'

  5. Do PDB Files Affect Performance?

    After a detour into Historical Debugging, it's time to come back to return to answering questions ab ...

  6. vue+uniapp实现照录像,相册选择 | 图片裁剪压缩,视频压缩

    一.插件简介 Zhimi-Camera(智密 - 智密 - 相机图册插件-视频/图片选择器)是一个支持拍照,录像,相册选择功能,自带图片裁剪,图片压缩,视频压缩,选择数量限制的uniapp原生插件.平 ...

  7. JAVA字符串去掉html代码,获取内容

    有时候我们需要在html代码中获取到文本内容,需要把html代码中的标签过滤掉 String htmlStr="html代码"; htmlStr = htmlStr.replace ...

  8. c++指针常量和常量指针概述

    个人理解,欢迎指正 这个简单,简单,简单(不要有心里压力:认为很难) 本文将会解决:  A.变与不变 B.判断指针常量和常量指针. C.常量指针指针常量.本文不涉及. 1.概述 A.指针: 说到底,还 ...

  9. 【Android开发】找乐,一个笑话App的制作过程记录

    缘起 想做一个笑话App的原因是因为在知乎上看过一个帖子,做Android可以有哪些数据可以练手,里面推荐了几个数据开放平台.在这些平台中无一不是有公共的笑话接口,当时心想这个可以拿来练手啊,还挺有意 ...

  10. 【LeetCode】979. Distribute Coins in Binary Tree 解题报告(C++)

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