随时找到数据流的中位

2024-02-15 05:58
文章标签 找到 数据流 随时 中位

本文主要是介绍随时找到数据流的中位,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【题目】 有一个源源不断地吐出整数的数据流,假设你有足够的空间来 保存吐出的数。请设计一个名叫MedianHolder的结构, MedianHolder可以随时取得之前吐出所有数的中位数。

【要求】 1.如果MedianHolder已经保存了吐出的N个数,那么任意时刻 将一个新数加入到MedianHolder的过程,其时间复杂度是 O(logN)。 2.取得已经吐出的N个数整体的中位数的过程,时间复杂度为 O(1)

寻找中位数是十分简单的,一串数据,排好序后,length为偶数就是中间的两个数的平均数。。。奇数为中间的数,,,小学知识

但是每次新进来一个数都要经历排序,每次排序的时间复杂度是远远大于O(1)的

方案

使用java提供的内置堆结构

堆结构简单来说就是,分为大根堆、小根堆

大根堆无论如何增删数据,第一个永远是最大的数据

小根堆同理

想详细理解的的请去熟悉下堆排序:堆排序

规则:

我们用一个大根堆Max、和一个小根堆Min去各自盛放这组数据的前一半、和后一半

那么前一半最大的数永远在第一个、后一半最小的数永远在第一个

执行规则

进来一个数,当Max为空时:加入Max堆else

这个数小于等于Max头部元素时,加入Max堆,else加入Min堆

--每次进数后,判断两个堆的大小是否差值大于1,如果大于1让比较多的那个堆从堆顶弹出一个给另一堆


一组示范

假设一组数据

5、3、1、0、2、4  --每个以次加入MedianHolder并获取中位数


当max为空时直接入Max

3、1、0、2、4

Max:5

Min:

此时只有一个数,他的中位数就是5


当max不为空时、判断下一个进来的数是否小于等于Max头部元素,是就加入Max

1、0、2、4

MaxPlie:5、3

MinPlie:

由于这样会导致两个堆中的数据量不平衡,规定,某个堆长度大于另一个堆1的时候无条件将头部元素给另一个堆

将5弹出给Min

MaxPlie:3

MinPlie:5

此时已经进入的数据中位数就是(5+3)/2=4


进来一个数1小于等于Max堆顶加入Max

0、2、4

Max:3、1

Min:5

中位数3


进来一个数0小于等于Max堆顶加入Max

2、4

Max:3、1、0

Min:5

需要铺平(差值过大,弹出一个给小的堆)

Max:1、0

Min:3、5

中位数 (1+3)/2=2


进来一个数2大于于Max堆顶加入Min堆

4

Max:1、0

Min:2、3、5

中位数2


进来一个数4大于Max堆顶加入Min堆

Max:1、0

Min:2、3、5、4

差值过大、需要铺平

Max:2、1、0

Min:3、5、4

中位数(2+3)/2=2.5


附加学习理解功能的代码


package basic_class_04;
import java.util.*;
public class Main {//快速中位数类public static class MedianHolder{//堆结构默认的是小根堆,,,这里插入一个比较器使堆变成大根堆private PriorityQueue<Integer> MaxHeap = new PriorityQueue<Integer>(11,new MaxSort());private PriorityQueue<Integer> MinHeap = new PriorityQueue<Integer>();public void addNumber(int num){if(MaxHeap.isEmpty()){MaxHeap.add(num);return;}if(num<=MaxHeap.peek()){MaxHeap.add(num);}else{MinHeap.add(num);}modifyTwoHeapsSize();// 每次添加后将两个堆铺平}public void modifyTwoHeapsSize(){if(MaxHeap.size()-MinHeap.size()==2){MinHeap.add(MaxHeap.poll());}if(MinHeap.size()-MaxHeap.size()==2){MaxHeap.add(MinHeap.poll());}}public Integer getMedian(){//取中位数,需要判断总数据量是奇数还是偶数int maxHeapSize = this.MaxHeap.size();int minHeapSize = this.MinHeap.size();if (maxHeapSize + minHeapSize == 0) {return null;}Integer maxHeapHead = this.MaxHeap.peek();Integer minHeapHead = this.MinHeap.peek();if(maxHeapSize==minHeapSize){return (maxHeapHead+minHeapHead)/2;}return maxHeapSize>minHeapSize?maxHeapHead:minHeapHead;}private static class MaxSort implements Comparator<Integer>{@Overridepublic int compare(Integer o1, Integer o2) {// TODO Auto-generated method stubreturn o2-o1;}}}public static void main(String[] args) {// TODO Auto-generated method stubint[] arr = {5,3,1,0,2,4};MedianHolder Medians = new MedianHolder();int[] newarr;int median;for(int i=0;i<arr.length;i++){newarr = Arrays.copyOfRange(arr,0,i);System.out.println(Arrays.toString(newarr));Medians.addNumber(arr[i]);System.out.println("+"+arr[i]);newarr = Arrays.copyOfRange(arr,0,i+1);System.out.println(Arrays.toString(newarr));median = Medians.getMedian();System.out.println("中位数"+median);System.out.println();}}}

不懂比较器?

比较器

这篇关于随时找到数据流的中位的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/710577

相关文章

数据流与Bitmap之间相互转换

把获得的数据流转换成一副图片(Bitmap) 其原理就是把获得倒的数据流序列化到内存中,然后经过加工,在把数据从内存中反序列化出来就行了。 难点就是在如何实现加工。因为Bitmap有一个专有的格式,我们常称这个格式为数据头。加工的过程就是要把这个数据头与我们之前获得的数据流合并起来。(也就是要把这个头加入到我们之前获得的数据流的前面)      那么这个头是

在二叉树中找到两个节点的最近公共祖先(基于Java)

如题  题解 public int lowestCommonAncestor(TreeNode root, int o1, int o2) {//记录遍历到的每个节点的父节点。Map<Integer, Integer> parent = new HashMap<>();Queue<TreeNode> queue = new LinkedList<>();parent.put(roo

微信小程序(一)数据流与数据绑定

一、单向数据流和双向数据流 1、单项数据流:指的是我们先把模板写好,然后把模板和数据(数据可能来自后台)整合到一起形成HTML代码,然后把这段HTML代码插入到文档流里面 优点:数据跟踪方便,流向单一,追寻问题比较方便【主要体现:微信小程序】。 缺点:就是写起来不太方便,如果修改UI界面数据需要维护对应的model对象 2、双向数据流:值和UI是双向绑定的,大家都知道,只要UI里面的值发生

PDF样本图册转换为一个二维码,随时扫码打开无需印刷

在这个数字化时代,纸质样本图册已成为过去。如今,一切都变得触手可及,包括我们的PDF样本图册。想象一下,将这些图册转换为一个二维码,让客户随时扫码打开,无需印刷,这将带来多大的便利和环保效益!接下来就让我来教你如何轻松实现PDF样本图册到二维码的转换,让您与时俱进,走在环保科技的前沿吧。 1. 准备好制作工具:FLBOOK在线制作电子杂志平台 2. 转换文档:点击开始

Spring是如何找到URL请求对应的Controller的

文章来源 原文作者:Spring MVC 原文地址: https://blog.csdn.net/hl233211/article/details/77450697 http://ddrv.cn/a/58528 本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。 序:先贴一张SpringMVC整体的框架原理图 此文主要描述Spring在响应请求的时候是如何根据U

LeetCode438. 找到字符串中所有字母异位词(2024秋季每日一题 11)

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。 示例 1: 输入: s = “cbaebabacd”, p = “abc” 输出: [0,6] 解释: 起始索引等于 0 的子串是 “cba”, 它是 “abc” 的异位词。 起始索引等于 6 的子串是

涨幅超过了90%,心动网络股价成V字后,TapTap找到流量源了吗?

心动公司发布了截至2024年6月30日止六个月的中期业绩。 在2024年上半年(24H1),公司实现总营收22.21亿元,较去年同期增长了26.7%。归属于母公司的净利润达到2.05亿元,同比激增127.4%。经调整后,归属于母公司的净利润更是攀升至2.37亿元,同比增长率高达110.0%。 与业绩对应的是股价变化。 自2024年初以来,在港股市场近30只游戏软件相关股票

关于win7下Django无法找到manage.py

前一段时间学习Python-Django,由于目前对Linux还不是很熟悉所以就在window下学习了,用的是Python3.3在建立个人blog时就是找不到Django生成的文件,可是也不显示出错,在网上找了很多说是bug经过认真仔细观察终于发现了在电脑C盘用户本机里面,现在写出来希望有需要的不要再浪费精力了

【算法:二分查找】java算法二分查找,如何通过二分查找找到重复元素的第一个,coding

二分查找算法,是基于有序的结果集进行查询的 二分查找的时间复杂度是O(logN) 写一段二分查询的代码: public static void main(String[] args) {int[] data = new int[]{1, 2, 3, 3, 5, 5, 6, 8, 9, 9, 10};int queryData = 5;int index = queryDataIndex(qu