剑指Offer-数据流中的中位数
时间:2022-05-11
本文章向大家介绍剑指Offer-数据流中的中位数,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
思路
思路一:
维护一个数组,每次加入后,进行排序,当总元素个数为奇数时,中位数就是数组中间的元素;当总元素个数为偶数时,中位数就是数组中间元素和前一个元素的平均数。
思路二:
- 维护一个大顶堆,一个小顶堆,且保证两点:
- 小顶堆里的元素全大于大顶堆里的元素;
- 两个堆个数的差值小于等于1;
- 当insert的数字个数为奇数时:使小顶堆个数比大顶堆多1;当insert的数字个数为偶数时,使大顶堆个数跟小顶堆个数一样;
- 当总元素个数为奇数时,中位数就是小顶堆堆顶;当总元素个数为偶数时,中位数就是两个个堆堆顶平均数。
代码实现
package Tree;
import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;
/**
* 数据流中的中位数
* 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
* 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
*/
public class Solution43 {
ArrayList<Integer> list = new ArrayList<>();
// 大顶堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
// 小顶堆,并且大顶堆元素都大于小顶堆
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
// 当前数据流读入的元素个数
int N = 0;
public static void main(String[] args) {
Solution43 solution43 = new Solution43();
solution43.Insert_2(3);
System.out.println(solution43.GetMedian_2());
solution43.Insert_2(4);
System.out.println(solution43.GetMedian_2());
}
/**
* 维护两个堆,一个大顶堆、一个小顶堆
*
* @param val
*/
public void Insert_2(Integer num) {
// 插入要保证两个堆存于平衡状态
if (N % 2 == 0) {
// N 为偶数的情况下插入到小顶堆。
// 因为大顶堆元素都要大于小顶堆,但是新插入的元素不一定比小顶堆元素来的大,
// 因此需要先将元素插入小顶堆,然后利用小顶堆为大顶堆的特点,取出堆顶元素即为最大元素,此时插入大顶堆
maxHeap.offer(num);
minHeap.offer(maxHeap.poll());
} else {
minHeap.offer(num);
maxHeap.offer(minHeap.poll());
}
N++;
}
public Double GetMedian_2() {
if (N % 2 == 0) {
return (maxHeap.peek() + minHeap.peek()) / 2.0;
} else {
return (double) minHeap.peek();
}
}
/**
* 维护数组,加入时排序
*
* @param num
*/
public void Insert(Integer num) {
list.add(num);
Collections.sort(list);
}
public Double GetMedian() {
int n = list.size();
if (n % 2 == 0) {
return Double.valueOf((list.get(n / 2) + list.get(n / 2 - 1)) / 2.0);
} else {
return Double.valueOf(list.get(n / 2));
}
}
}
- 2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛
- 2020: [Usaco2010 Jan]Buying Feed, II
- 2102: [Usaco2010 Dec]The Trough Game
- 洛谷P3707 [SDOI2017]相关分析(线段树)
- Java计数器之CountDownLatch、CyclicBarrier、Semaphore
- 再看最短路算法 1 —— 单源最短路
- 3402: [Usaco2009 Open]Hide and Seek 捉迷藏
- 1084: [SCOI2005]最大子矩阵
- 关于一般的并查集求根操作的一组对照研究
- vue计算属性详解——小白速会
- 【技巧】Java工程中的Debug信息分级输出接口及部署模式
- 1934: [Shoi2007]Vote 善意的投票
- 算法模板——线段树8 (字符串回文变换)
- 算法模板——哈希单模板字符串匹配
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 简单了解Python变量作用域正确使用方法
- Python实现Keras搭建神经网络训练分类模型教程
- keras导入weights方式
- 使用Keras实现简单线性回归模型操作
- 音频处理 windows10下python三方库librosa安装教程
- Python Excel vlookup函数实现过程解析
- 浅谈Python 函数式编程
- Keras-多输入多输出实例(多任务)
- 利用Vscode进行Python开发环境配置的步骤
- python + selenium 刷B站播放量的实例代码
- 巧用x-cos-traffic-limit header来限制上传下载速率
- centos7上编译安装php7以php-fpm方式连接apache
- 基于Python实现视频的人脸融合功能
- 如何理解python对象
- Virtualenv 搭建 Py项目运行环境的教程详解