【leetcode】Find Median From Data Stream

news/2024/11/28 10:56:27/

参考资料:左神算法课+《剑指offer》
295. Find Median from Data Stream
The median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value, and the median is the mean of the two middle values.

For example, for arr = [2,3,4], the median is 3.
For example, for arr = [2,3], the median is (2 + 3) / 2 = 2.5.
Implement the MedianFinder class:

MedianFinder() initializes the MedianFinder object.
void addNum(int num) adds the integer num from the data stream to the data structure.
double findMedian() returns the median of all elements so far. Answers within 10-5 of the actual answer will be accepted.

Example 1:
Input
[“MedianFinder”, “addNum”, “addNum”, “findMedian”, “addNum”, “findMedian”]
[[], [1], [2], [], [3], []]
Output
[null, null, null, 1.5, null, 2.0]

Explanation
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1); // arr = [1]
medianFinder.addNum(2); // arr = [1, 2]
medianFinder.findMedian(); // return 1.5 (i.e., (1 + 2) / 2)
medianFinder.addNum(3); // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0

观察到:小于中位数的数的个数 与 大于中位数的数的个数 相差 <=1 ; 如果对数组排序的话,小于中位数的数 总是 位于 中位数 左侧,大于中位数的数总是 位于中位数右侧。

思路:建立大根堆、小根堆,第一个数据来到后,先进大根堆;之后的数,与大根堆的堆顶比较,决定它进大根堆还是小根堆。具体地,如果新数小于大根堆堆顶,那么进大根堆;如果新数大于大根堆堆顶,那么进小根堆。然后,调整两个堆(balance()),使得二者size相差≤1,这样才能“暴露”出两个“预备中位数“(指大根堆、小根堆的堆顶),便于找出中位数。

《剑指offer》给出的思路与之类似,但是 在维护两个堆大小的调整上有些别扭(个人感觉),而 算法课 给出的代码更自然——先往大根堆里加,后来的数与大根堆堆顶比较,加入到相应的堆中后,用balance函数一起调整两个堆的size。

class MedianFinder{private PriorityQueue<Integer> minh;private PriorityQueue<Integer> maxh;public MedianFinder(){minh = new PriorityQueue<>((a,b)->a-b);maxh = new PriorityQueue<>((b,a)->b-a);}public void addNum(int num){if(maxh.isEmpty()){maxh.add(num);}else{if(maxh.peek()>=num){maxh.add(num);}else {minh.add(num);}}balance();}public void balance(){if(maxh.size()-minh.size()==2){minh.add(maxh.poll());}if(minh.size()-maxh.size()==2){maxh.add(minh.poll());}}public double findMedian(){if(((maxh.size()+minh.size())&1)==1){// oddreturn maxh.size()>minh.size()?maxh.peek():minh.peek();}else {return (double)(maxh.peek()+minh.peek())/2;}}}

http://www.ppmy.cn/news/88402.html

相关文章

【C++初阶】动态内存管理

一.C内存分布 说明&#xff1a; 1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长的&#xff1b; 2. 内存映射段是高效的I/O映射方式&#xff0c;用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存&#xff0c;做进程间通信&…

H-THNSJ0A温湿度传感器标准modbus 通讯协议

1、 概述 1&#xff0e;1 引言 通讯规约详细描述了本机通讯的读、写命令格式及信息和数据的定义&#xff0c;以便第三方开发使用。 1. 2 电气特点及符合标准 1) 连接上位机的主通信接口&#xff0c;MODUBS RTU 协议标准。 2) 信息传输方式为异步方式&#xff0c;字节格式为…

Leetcode 221. 最大正方形

Leetcode 221. 最大正方形题目 在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内&#xff0c;找到只包含 ‘1’ 的最大正方形&#xff0c;并返回其面积。m matrix.lengthn matrix[i].length1 < m, n < 300matrix[i][j] 为 ‘0’ 或 ‘1’ 解法 动态规划状态压缩&#xff1a;定…

Android系统原理性问题分析 - 单路情况下的C/S模型

声明 在Android系统中经常会遇到一些系统原理性的问题&#xff0c;在此专栏中集中来讨论下。Android系统中很多地方都采用了I/O多路复用的机制&#xff0c;为了引出I/O多路复用机制&#xff0c;先来分析多路并发情况下的C/S模型。此篇参考一些博客和书籍&#xff0c;代码基于A…

Java的ssm框架中开发常用注解的作用和功能小小总结!!!

Java 的 SSM (Spring SpringMVC MyBatis) 框架是 Java Web 开发中常用的框架之一。其中&#xff0c;Spring、SpringMVC、MyBatis 框架各自都提供了很多注解&#xff0c;以下是一些常用注解及其功能&#xff1a; Spring 框架常用注解 Component&#xff1a;用于标记一个类为组…

视频会议产品对比分析

内网视频会议系统如何选择&#xff1f;有很多单位为了保密&#xff0c;只能使用内部网络&#xff0c;无法连接互联网&#xff0c;那些SaaS视频会议就无法使用。在内网的优秀视频会议也有很多可供选择&#xff0c;以下是几个常用的&#xff1a; 1. 宝利通&#xff1a;它支持多种…

2019下半年上午题

2019下半年上午题 b 选a c 最后统一单位 计算需要多少片芯片&#xff1a; 流水线&#xff1a; 也就是&#xff1a; 对于这一道题&#xff1a; c ssl&#xff1a;安全套接层 https&#xff1a;安全通道 PGP&#xff1a;电子邮件加密 d b a b b 受委托方和委…

Java枚举

Java枚举 &#x1f37a;1 背景及定义&#x1f37a;&#x1f9c3;2 使用&#x1f9c3;&#x1f964;3 枚举优点缺点&#x1f964;&#x1f375;4 枚举和反射&#x1f375;&#x1f377;4.1 枚举是否可以通过反射&#xff0c;拿到实例对象呢&#xff1f;&#x1f377; ☕️5 总结…