参考 https://blog.csdn.net/u011080472/article/details/51291089

题目描述

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

分析

获取中位数有多种方法,但是各种方法的时间效率不一。下面是多种方法的时间复杂度的比较:有图可以知道使用AVL二叉平衡树的方法和使用最大堆最小堆的方法是总的时间复杂度最优的。但是AVL二叉平衡树没有现成的数据结构的实现,因此可以考虑java集合中的PriorityQueue优先队列(也就是堆,默认为小根堆)来实现比较高校的中位数查找。

有关优先队列PriorityQueue,请参考https://www.cnblogs.com/lijingran/p/9143510.html

思路:考虑将数据序列从中间开始分为两个部分,左边部分使用大根堆表示,右边部分使用小根堆存储。每遍历一个数据,计数器count增加1,当count是偶数时,将数据插入小根堆;当count是奇数时,将数据插入大根堆。当所有数据遍历插入完成后(时间复杂度为O(logn)

,如果count最后为偶数,则中位数为大根堆堆顶元素和小根堆堆顶元素和的一半;如果count最后为奇数,则中位数为小根堆堆顶元素。

牛客AC:

import java.util.PriorityQueue;
import java.util.Comparator; public class Solution { private int count = ; // 数据流中的数据个数
// 优先队列集合实现了堆,默认实现的小根堆
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
// 定义大根堆,更改比较方式
private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1; // o1 - o2 则是小根堆
}
}); public void Insert(Integer num) {
if ((count & ) == ) {
// 当数据总数为偶数时,新加入的元素,应当进入小根堆
// (注意不是直接进入小根堆,而是经大根堆筛选后取大根堆中最大元素进入小根堆)
// 1.新加入的元素先入到大根堆,由大根堆筛选出堆中最大的元素
maxHeap.offer(num);
int filteredMaxNum = maxHeap.poll();
// 2.筛选后的【大根堆中的最大元素】进入小根堆
minHeap.offer(filteredMaxNum);
} else {
// 当数据总数为奇数时,新加入的元素,应当进入大根堆
// (注意不是直接进入大根堆,而是经小根堆筛选后取小根堆中最大元素进入大根堆)
// 1.新加入的元素先入到小根堆,由小根堆筛选出堆中最小的元素
minHeap.offer(num);
int filteredMinNum = minHeap.poll();
// 2.筛选后的【小根堆中的最小元素】进入小根堆
maxHeap.offer(filteredMinNum);
}
count++;
} public Double GetMedian() {
// 数目为偶数时,中位数为小根堆堆顶元素与大根堆堆顶元素和的一半
if ((count & ) == ) {
return new Double((minHeap.peek() + maxHeap.peek())) / ;
} else {
return new Double(minHeap.peek());
}
} }

剑指offer(65):获取数据流中的中位数的更多相关文章

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

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

  2. 剑指Offer——算法复杂度中的O(logN)底数是多少

    剑指Offer--算法复杂度中的O(logN)底数是多少 前言 无论是计算机算法概论.还是数据结构书中,关于算法的时间复杂度很多都用包含O(logN)这样的描述,但是却没有明确说logN的底数究竟是多 ...

  3. 《剑指offer》旋转数组中的最小数字

    本题来自<剑指offer> 旋转数组中的最小数字 题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例 ...

  4. 剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers)

    剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers) https://leetcode.com/problems/sum-of-two-in ...

  5. 剑指 Offer 65. 不用加减乘除做加法 + 位运算

    剑指 Offer 65. 不用加减乘除做加法 Offer_65 题目描述 题解分析 java代码 package com.walegarrett.offer; /** * @Author WaleGa ...

  6. 剑指 Offer 56 - II. 数组中数字出现的次数 II + 位运算

    剑指 Offer 56 - II. 数组中数字出现的次数 II Offer_56_2 题目详情 解题思路 java代码 package com.walegarrett.offer; /** * @Au ...

  7. 剑指 Offer 56 - I. 数组中数字出现的次数 + 分组异或

    剑指 Offer 56 - I. 数组中数字出现的次数 Offer_56_1 题目描述 解题思路 java代码 /** * 方法一:数位方法 */ class Offer_56_1_2 { publi ...

  8. 剑指 Offer 44. 数字序列中某一位的数字 + 找规律 + 数位

    剑指 Offer 44. 数字序列中某一位的数字 Offer_44 题目描述 题解分析 java代码 package com.walegarrett.offer; /** * @Author Wale ...

  9. 【剑指Offer】旋转数组中的最小数字 解题报告(Python)

    [剑指Offer]旋转数组中的最小数字 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://www.nowcoder.com/ta/coding-intervie ...

  10. 【剑指Offer】删除链表中重复的结点 解题报告(Python)

    [剑指Offer]删除链表中重复的结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interview ...

随机推荐

  1. A股牛蹄板块轮动迹象

    2018年10月熊市末期牛市初期 1.券商 2.中小银行 3.稀土永磁 4.铁路基建 5.人工智能 6.电器仪表 7.保险 8.非进金融.供热供气

  2. spring boot拦截器

    实现自定义拦截器只需要3步: 1.创建我们自己的拦截器类并实现 HandlerInterceptor 接口. 2.创建一个Java类继承WebMvcConfigurerAdapter,并重写 addI ...

  3. 介绍几款Web服务器性能压力测试工具

    一.http_load 程序非常小,解压后也不到100K http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载. 但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般 ...

  4. python循环切片

    x = [0,99, 'a', 1, 2, 'b',5, 3, 0,'a' ,1, 8, 5,'b',5,9,5] b=[] c=[] d=[] for i in range(len(x)): if ...

  5. C++判断一个文件是否可以正确打开的代码

    /* fopen example */ #include <iostream> #include <conio.h> using namespace std; int main ...

  6. cocos2d-x 3.9 android studio项目命令行打包

    进入创建的项目的 proj.android-studio目录 cocos run/compile -p android --android-studio 这样就可以打包了

  7. jq js 的date()使用

    Js获取当前日期时间及其它操作 var myDate = new Date();myDate.getYear(); //获取当前年份(2位)myDate.getFullYear(); //获取完整的年 ...

  8. Python基础-操作mysql

    mysql 属于第三方模块,需要先安装 pip install pymysql,sql执行后,数据获取函数有三种cur.fetchone()#获取第一条数据,依次类推下去,第二次执行时候,就会取除去第 ...

  9. PHP 使用header函数设置HTTP头的示例解析 表头

    PHP 使用header函数设置HTTP头的示例解析 表头 //定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header ...

  10. rabbitmq-交换机

    四种交换机: direct fanout topic headers http://www.jianshu.com/p/469f4608ce5d