【Java】 剑指offer(41) 数据流中的中位数
本文参考自《剑指offer》一书,代码采用Java语言。
题目
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
思路
所谓数据流,就是不会一次性读入所有数据,只能一个一个读取,每一步都要求能计算中位数。
将读入的数据分为两部分,一部分数字小,另一部分大。小的一部分采用大顶堆存放,大的一部分采用小顶堆存放。当总个数为偶数时,使两个堆的数目相同,则中位数=大顶堆的最大数字与小顶堆的最小数字的平均值;而总个数为奇数时,使小顶堆的个数比大顶堆多一,则中位数=小顶堆的最小数字。
因此,插入的步骤如下:
1.若已读取的个数为偶数(包括0)时,两个堆的数目已经相同,将新读取的数插入到小顶堆中,从而实现小顶堆的个数多一。但是,如果新读取的数字比大顶堆中最大的数字还小,就不能直接插入到小顶堆中了 ,此时必须将新数字插入到大顶堆中,而将大顶堆中的最大数字插入到小顶堆中,从而实现小顶堆的个数多一。
2若已读取的个数为奇数时,小顶堆的个数多一,所以要将新读取数字插入到大顶堆中,此时方法与上面类似。
测试算例
1.功能测试(读入奇/偶数个数字)
2.边界值测试(读入0个、1个、2个数字)
Java代码
//题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么
//中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,
//那么中位数就是所有数值排序之后中间两个数的平均值。 import java.util.PriorityQueue;
import java.util.Comparator; public class StreamMedian {
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
public int compare(Integer i1,Integer i2){
return i2-i1;
}
});
public void Insert(Integer num) {
if(((minHeap.size()+maxHeap.size())&1)==0){//偶数时,下个数字加入小顶堆
if(!maxHeap.isEmpty() && maxHeap.peek()>num){
maxHeap.offer(num);
num=maxHeap.poll();
}
minHeap.offer(num);
}else{//奇数时,下一个数字放入大顶堆
if(!minHeap.isEmpty() && minHeap.peek()<num){
minHeap.offer(num);
num=minHeap.poll();
}
maxHeap.offer(num);
}
} public Double GetMedian() {
if((minHeap.size()+maxHeap.size())==0)
throw new RuntimeException();
double median;
if((minHeap.size()+maxHeap.size()&1)==0){
median=(maxHeap.peek()+minHeap.peek())/2.0;
}else{
median=minHeap.peek();
}
return median;
}
}
收获
1.最大最小堆可以用PriorityQueue实现,PriorityQueue默认是一个小顶堆,通过传入自定义的Comparator函数可以实现大顶堆:
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
@Override
public int compare(Integer i1,Integer i2){
return i2-i1; //降序排列
}
});
PriorityQueue的常用方法有:poll(),offer(Object),size(),peek()等。
2.平均值应该定义为double,且(a+b)/2.0 。
3.往最大堆中插入数据时间复杂度是O(logn),获取最大数的时间复杂度是O(1)。
4.这道题关键在于分成两个平均分配的部分,奇偶时分别插入到最大最小堆中,利用最大最小堆性质的插入方法要掌握。
【Java】 剑指offer(41) 数据流中的中位数的更多相关文章
- 剑指 Offer 41. 数据流中的中位数 + 堆 + 优先队列
剑指 Offer 41. 数据流中的中位数 Offer_41 题目详情 题解分析 本题使用大根堆和小根堆来解决这个寻找中位数和插入中位数的问题. 其实本题最直接的方法是先对数组进行排序,然后取中位数. ...
- 每日一题 - 剑指 Offer 41. 数据流中的中位数
题目信息 时间: 2019-06-30 题目链接:Leetcode tag: 大根堆 小根堆 难易程度:中等 题目描述: 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有 ...
- [剑指offer] 41. 数据流中的中位数 (大小堆,优先队列)
对于海量数据与数据流,用最大堆,最小堆来管理. class Solution { public: /* * 1.定义一个规则:保证左边(大顶堆)和右边(小顶堆)个数相差不大于1,且大顶堆的数值都小于等 ...
- 【剑指Offer】数据流中的中位数 解题报告(Python)
[剑指Offer]数据流中的中位数 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...
- Go语言实现:【剑指offer】数据流中的中位数
该题目来源于牛客网<剑指offer>专题. 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位 ...
- 剑指offer:数据流中的中位数(小顶堆+大顶堆)
1. 题目描述 /** 如何得到一个数据流中的中位数? 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值. 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两 ...
- 剑指Offer 63. 数据流中的中位数(其他)
题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值.我们 ...
- 《剑指offer》-数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 最开始的思路 ...
- [剑指Offer] 63.数据流中的中位数
题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. c ...
随机推荐
- Java开发中各种集合框架简介
在大数据MapReduce作业开发中,我们经常会遇到一些大小表的join,这是如果这个小表足够“小”的话,我们可以使用进行“map-join-side”,这要就可以有效的降低reduce端的压力,但是 ...
- pyinstaller 打包不成功,提示inporterror 缺少xlrd、xlwt
问题:pyinstaller 打包不成功,提示inporterror 缺少xlrd.xlwt 解决:将 pypiwin 230 改为 219
- A - 最大子矩阵 HYSBZ - 1084 (DP)
题目链接:https://cn.vjudge.net/contest/281963#problem/A 题目大意:中文题目 具体思路:观察到m<=2,所以我们可以对两种情况进行单独讨论,当m== ...
- android当前网络连接类型判断
package net.nyist.netState; import android.content.Context; import android.net.ConnectivityManager; ...
- escape、encodeURI和encodeURIComponent的区别
1.简单解释 简单来说,escape是对字符串(string)进行编码(而另外两种是对URL),作用是让它们在所有电脑上可读. 编码之后的效果是%XX或者%uXXXX这种形式. 其中 ASCII字母. ...
- Python3 configparse模块(配置)
ConfigParser模块在python中是用来读取配置文件,配置文件的格式跟windows下的ini配置文件相似,可以包含一个或多个节(section),每个节可以有多个参数(键=值). 注意:在 ...
- 工作中bug笔记
1.报Cannot read property indexOf of undefined 错误的时候!!!报这种错的时候,一般是因为indexOf前面检查的东西是不存在的!!!!! 2.使用< ...
- nagios系列(三)之nagios被动监控模式之添加系统负载load、swap、磁盘iostat及memory内存监控详解
环境: nagios server:192.168.8.42 host_name:node4.chinasoft.com nagios client:192.168.8.41 host_name:no ...
- springboot:session集中存储到redis
1.在web工程的基础上,在pom.xml中添加: <dependency> <groupId>org.springframework.boot</groupId> ...
- gulp自动化构建教程
gulp及gulpfile.js编写示例 本文主要记录一个gulpfile.js示例,以免以后用的时候遗忘.但首先还是要了解gulp是什么以及如何使用. 一.什么是gulp 简单来说:就是压缩前 ...