海量数据找中位数

2023-11-12

腾讯一面问到了,用的算法导论中的Kth算法,期望时间复杂度为O(n)。后来想了想,万一数据多的来根本不能一次读入内存,这个时候该如何解决呢?

题目如下:
只有2G内存的pc机,在一个存有10G个整数的文件,从中找到中位数,写一个算法。

http://blog.sina.com.cn/s/blog_4a8aac970100093j.html~type=v5_one&label=rela_nextarticle

给出了四种方法来解决

算法:
1.利用外排序的方法,进行排序 ,然后再去找中位数
 
2.另外还有个思路利用堆
先求第1G大,然后利用该元素求第2G大,然后利用第2G大,求第3G大...当然这样的话虽不需排序,但是磁盘操作会比较多,具体还需要分析下与外排序的效率哪个的磁盘IO会比较多
建立一个1g个整数的最大值堆,如果元素小于最大值则入堆,这样可以得到第1g大的那个元素然后利用这个元素,重新建一次堆,这次入堆的条件还要加上大于这个第1g大的元素,这样建完堆可以得到第2g大的那个...
 
3.借鉴基数排序思想
偶认为可以用位来判断计数,从最高位到最低位,为了方便表述我们假设为无符号整数,即0x00000000~0xFFFFFFFF依次递增,那么可以遍历所有数据,并记录最高位为0和1的个数(最高位为0的肯定是小于最高位为1的)记为N0、N1
那么根据N0和N1的大小就可以知道中位数的最高位是0还是1
假设N0>N1,那么再计算N00和N01,
如果N00>(N01+N1),则说明中位数的最高两位是00
再计算N000和N001.。。。依次计算就能找到中位数
 
如果改进一下,设定多个计数器
好像一次磁盘io也可以统计出N0,N00,....的数值
 
4.借鉴桶排序思想
一个整数假设是32位无符号数
第一次扫描把0~2^32-1分成2^16个区间,记录每个区间的整数数目
找出中位数具体所在区间65536*i~65536*(i+1)-1
第二次扫描则可找出具体中位数数值

第一次扫描已经找出中位数具体所在区间65536*i~65536*(i+1)-1

然后第二次扫描再统计在该区间内每个数出现的次数,就可以了


http://blog.csdn.net/sytu_hzj/article/details/6856775

也有叙述

题目:在一个文件中有 10G 个整数,乱序排列,要求找出中位数。内存限制为 2G。只写出思路即可(内存限制为 2G的意思就是,可以使用2G的空间来运行程序,而不考虑这台机器上的其他软件的占用内存)。

 

 

分析:既然要找中位数,很简单就是排序的想法。那么基于字节的桶排序是一个可行的方法

思想:将整形的每1byte作为一个关键字,也就是说一个整形可以拆成4个keys,而且最高位的keys越大,整数越大。如果高位keys相同,则比较次高位的keys。整个比较过程类似于字符串的字典序。

第一步:把10G整数每2G读入一次内存,然后一次遍历这536,870,912个数据。每个数据用位运算">>"取出最高8位(31-24)。这8bits(0-255)最多表示255个桶,那么可以根据8bit的值来确定丢入第几个桶。最后把每个桶写入一个磁盘文件中,同时在内存中统计每个桶内数据的数量,自然这个数量只需要255个整形空间即可。

代价:(1) 10G数据依次读入内存的IO代价(这个是无法避免的,CPU不能直接在磁盘上运算)。(2)在内存中遍历536,870,912个数据,这是一个O(n)的线性时间复杂度。(3)把255个桶写会到255个磁盘文件空间中,这个代价是额外的,也就是多付出一倍的10G数据转移的时间。

第二步:根据内存中255个桶内的数量,计算中位数在第几个桶中。很显然,2,684,354,560个数中位数是第1,342,177,280个。假设前127个桶的数据量相加,发现少于1,342,177,280,把第128个桶数据量加上,大于1,342,177,280。说明,中位数必在磁盘的第128个桶中。而且在这个桶的第1,342,177,280-N(0-127)个数位上。N(0-127)表示前127个桶的数据量之和。然后把第128个文件中的整数读入内存。(平均而言,每个文件的大小估计在10G/128=80M左右,当然也不一定,但是超过2G的可能性很小)。

代价:(1)循环计算255个桶中的数据量累加,需要O(M)的代价,其中m<255。(2)读入一个大概80M左右文件大小的IO代价。

注意,变态的情况下,这个需要读入的第128号文件仍然大于2G,那么整个读入仍然可以按照第一步分批来进行读取。

第三步:继续以内存中的整数的次高8bit进行桶排序(23-16)。过程和第一步相同,也是255个桶。

第四步:一直下去,直到最低字节(7-0bit)的桶排序结束。我相信这个时候完全可以在内存中使用一次快排就可以了。

 

 

整个过程的时间复杂度在O(n)的线性级别上(没有任何循环嵌套)。但主要时间消耗在第一步的第二次内存-磁盘数据交换上,即10G数据分255个文件写回磁盘上。一般而言,如果第二步过后,内存可以容纳下存在中位数的某一个文件的话,直接快排就可以了。关于快排的效率,可以看看我博客中的数据



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

海量数据找中位数 的相关文章

  • 如何使用 System.out.println 以十六进制打印字节?

    我已经声明了一个字节数组 我使用的是 Java byte test new byte 3 test 0 0x0A test 1 0xFF test 2 0x01 如何打印数组中存储的不同值 如果我使用 System out println
  • 在java中将StreamWriter转换为OutputStream?

    我正在尝试使用 System setOut 将 System out 重定向到字符串 它需要一个 PrintStream 有什么方法可以将 StringWriter 转换为 Stream 以便我可以将其传递给 setOut 吗 你不能完全这
  • 从内存中发送图像

    我正在尝试为 Discord 机器人实现一个系统 该系统可以动态修改图像并将其发送给机器人用户 为此 我决定使用 Pillow PIL 库 因为它对于我的目的来说似乎简单明了 这是我的工作代码的示例 它加载一个示例图像 作为测试修改 在其上
  • 为什么 .NET 异步等待文件复制比同步 File.Copy() 调用消耗更多 CPU?

    为什么下面的代码会产生 public static class Program public static void Main params string args var sourceFileName C Users ehoua Desk
  • 在 Go 中,如何将结构体转换为字节数组?

    我有一个我定义的结构实例 我想将其转换为字节数组 我尝试了 byte my struct 但这不起作用 另外 我还被指出二进制包 http golang org pkg encoding binary 但我不确定我应该使用哪个函数以及应该如
  • 如何使用 open with 语句打开文件

    我正在研究如何在 Python 中进行文件输入和输出 我编写了以下代码 将一个文件中的名称列表 每行一个 读取到另一个文件中 同时根据文件中的名称检查名称并将文本附加到文件中出现的位置 该代码有效 可以做得更好吗 我想用with open
  • Java byte[] 与 String 之间的转换

    为什么这个junit测试失败了 import org junit Assert import org junit Test import java io UnsupportedEncodingException public class T
  • MPI 从文本文件中读取

    我正在学习 MPI 编程 我遇到了这个问题 假设我有一个包含 100 000 行 行的 txt 文件 如何将它们分块以供 4 个处理器处理 即我想让处理器 0 负责第 0 25000 行的处理 让处理器 1 负责第 25001 50000
  • Python 中的字节数组

    如何在 Python 中表示字节数组 如 Java 中的 byte 我需要用 gevent 通过网络发送它 byte key 0x13 0x00 0x00 0x00 0x08 0x00 在Python 3中 我们使用bytes对象 也称为s
  • 为什么 C# 中 bool 数据类型的大小不是只有 1 位?

    我刚刚学习 C 并深入研究数据类型 为什么不是一个bool数据类型大小为 1 位 看起来它只能保存两个值之一 true 或 false 那么这不是只占用 1 位空间来表示该值吗 是因为值的最小 可寻址 大小是一个字节 8 位 吗 这个帖子
  • 在C中提取字节

    我正在用 C 编写一个程序 我要提取字节 un8 extractbyte int r int pos 应该从数字 r 返回字节数 pos 例如 我使用作为输入 0x7788AABB 那么输出应该是 零件号 0 是 BB零件号 1 是 AA零
  • 如何在 Java 中读取/转换 InputStream 为字符串?

    如果你有一个java io InputStream对象 您应该如何处理该对象并生成一个String 假设我有一个InputStream包含文本数据 我想将其转换为String 例如我可以将其写入日志文件 最简单的方法是什么InputStre
  • 信号处理程序内的格式化 I/O

    我想编写一个 SIGSEGV 处理程序 将消息写入文件 FILE 我听说 fprintf 不可重入 不应在信号处理程序内调用 是否有它的可重入版本 或者任何其他提供可以在信号处理程序内部调用的格式化文件 I O 的函数 否 根据C11标准N
  • 字节数组到 Excel 工作簿

    我正在尝试将字节数组转换为 Excel 工作簿 当我这样做时 Response BinaryWrite renderedBytes 它工作正常并且文件符合预期 但是当我尝试用我在网上找到的这个来做到这一点时 private Object B
  • 谁能解释一下 GHC 对 IO 的定义吗?

    标题非常自我描述 但有一个部分引起了我的注意 newtype IO a IO State RealWorld gt State RealWorld a 剥离newtype 我们得到 State RealWorld gt State Real
  • 这个程序有什么问题?

    include
  • 尝试删除文件时如何调试“共享冲突”

    我有一个多线程 C 应用程序 它创建文件 打开文件进行处理 然后在完成后删除它们 此应用程序预计会处理 1 100 个文件 当我尝试在处理后删除文件时 有点随机 很可能归因于应用程序的多线程性质 我遇到共享冲突 我的直觉告诉我 维克 你在尝
  • 如何使用用户输入变量作为通用包的参数?

    In Stack adb我指定了两个参数 大小和类型 我想创建一个堆栈 该堆栈的数据类型与用户在我的堆栈中指定的数据类型完全相同multistack adb file 我似乎找不到一种方法来创建新的包或使用用户定义的堆栈类型变量来实例化堆栈
  • 什么是输入流和输出流?我们为什么以及何时使用它们?

    有人向我解释一下什么InputStream and OutputStream are 我对两者的用例感到困惑InputStream and OutputStream 如果您还可以包含一段代码来配合您的解释 那就太好了 谢谢 目标是Input
  • 命名管道性能问题

    我使用命名管道进行 C 和 Delphi 之间的过程间通信 C 使用System IO Pipes包 而 Delphi 使用Libby s pipes pas 不幸的是 通信几乎是高性能的 分析显示通信占用了整个运行时间的 72 其余的用于

随机推荐

  • 订单、支付、退款、发货、退货等编号自动生成类

    在商城网站中 订单编号的自动生成 ERP中各个单据的编号自动生成 都可以按照一下的方式来自动生成 第一步 定义常量订单编号前缀 订单编号起始数 订单编号步长 public static final String ORDER SN PREFI
  • 固定资产批导程序

    Responsibility Program Name ZFIC001 Date written Author s name SongQiong Last update Program title 固定资产期初批量导入程序 Project
  • 【基础知识】5、相机内外参矩阵和坐标变换

    文章目录 1 世界坐标系和相机坐标系的关系 从世界坐标系到相机坐标系 涉及到物体的旋转和平移 绕着不同的坐标轴旋转不同的角度 得到相应的旋转矩阵 如下图所示 于是 从世界坐标系到相机坐标系 涉及到旋转和平移 其实所有的运动也可以用旋转矩阵和
  • npcap关闭_npcap是什么软件

    npcap是一个网络数据包抓包工具 是WinPcap的改进版 它支持NDIS 6技术 只允许管理员Administrator 访问Npcap 与WinPcap兼容或并存两种模式 支持Windows平台的回环数据包采集和发送 本教程操作环境
  • 性能测试_JMeter中你可能会忽略的细节点-2

    目录 CSV参数化有什么缺陷 在哪里可以体验到 JDBC请求报错Variable Name must not be null in JDBC Request 助攻机tar包和zip包要注意的事项 文件夹的执行权限 JMeter分布式主机假死
  • ACLR指标

    文章目录 一 ACLR含义 二 ACLR来源 一 ACLR含义 ACLR Adjacent Channel Leakage Power Ratio 测试目的 避免对邻近信道产生干扰 LTE和ACLR测试除了需要测试自身带宽相同的邻信道泄漏功
  • okGo详细使用步骤(一)

    OkGo的使用 一 详细使用方式可以直接观看源文档wiki 这里不再说明 本文档也是依赖于源文档进行代码测试和理解写的 写此文档时okgo版本 compile com lzy net okgo 3 0 4 几个库的介绍 library名 简
  • basler相机pylon安装及API调用

    1 官网下载basler相机的pylon 2 安装pylon 2 1选择pylon的模式 二次开发选择development模式 2 2选择接口 看相机的接口类型 选择相机的接口类型一般为GitE和USB类型 3 完后安装就打开Pylon
  • AUBO机械臂常用函数和指令详解(C/C#版本)

    我是厂妹 扩充一下上一篇内容 C 引用的C生成的DLL 所以直接一起介绍 部分不同会写出来 目录 头文件和引用部分 初始化和主要参数 根据基础坐标系运动操作 机械臂轴动 运动函数 设置基于基座系运动偏移量 获取机械臂当前位置信息 获取机械臂
  • FlowJo 10.4.0(流式细胞分析器工具)

    FlowJo mac是一款流式细胞仪数据分析软件 广泛用于生物医学研究领域 它提供了强大的功能和直观的用户界面 使用户能够对流式细胞仪收集的数据进行高级分析和可视化 FlowJo for mac具有以下主要特点 数据导入和预处理 FlowJ
  • oracle连接mysql详解linux_Linux平台Oracle连接MySQL

    前言 Windows平台Oracle连接MySQL的方法已经给大家介绍过了 现在大部分的Oracle和MySQL都是在Linux平台上面 刚好最近也有这种需求 顺手把整个搭建过程记录起来和大家分享 原理 通过ODBC连接MySQL的原理图
  • LU分解(LU Factorization)计算方法(手算+MATLAB),关于置换矩阵(Permutation Matrix),部分主元消去法(Partial Pivoting)

    背景 求解一些列具有相同系数矩阵的线性方程 如 A x b 1 Ax b 1 Ax b1
  • Python爬虫之Jsonpath解析

    Jsonpath的安装方式 pip install jsonpath i https pypi douban com simple 利用国内源速度快一些 jsonpath的使用 针对json数据结构进行数据解析 本地文件 服务器文件需要先下
  • 2023年黑客零基础从入门到精通学习成长路线(超多图、非常详细),看完这一篇就够了。

    怎样规划学习路线 如果你是一个安全行业新人 我建议你先从网络安全或者Web安全 渗透测试这两个方向先学起 一是市场需求量高 二则是发展相对成熟入门比较容易 值得一提的是 学网络安全 是先网络后安全 学Web安全 也是先Web再有安全 安全不
  • mysql 存储过程参考 虽然不建议用存储过程,一个例子 用于自己参考

    BEGIN DECLARE done INT DECLARE v companyName VARCHAR 100 DECLARE v phone VARCHAR 30 DECLARE v contactName VARCHAR 30 DEC
  • 论文笔记:On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima

    2017 ICLR 0 摘要 这篇文章探究了深度学习中一个普遍存在的问题 使用大的batchsize训练网络会导致网络的泛化性能下降 Generalization Gap 大的batchsize训练使得目标函数倾向于收敛到sharp min
  • ubuntu18.04 安装OpenBLAS

    一 通过apt get安装 sudo apt get install libopenblas dev 二 源码安装 下载OpenBLAS并安装 git clone https github com xianyi OpenBLAS git c
  • [人工智能-深度学习-37]:卷积神经网络CNN - 重构神经网络的疑惑与思考?

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 人工智能 深度学习 37 卷积神经网络CNN 重构神经网络的疑惑与思考 文火冰糖 王文兵 的博客 CSDN博客 如果你看懂我的疑惑 如果你能
  • MYSQL的server层和存储引擎层分析

    转自 微点阅读 https www weidianyuedu com SQL的全称是Structured Query Language 翻译成中国话就是结构化查询语言 这是一种声明式的语法 何为声明式 对于设计数据库的人而言 语句怎么执行就
  • 海量数据找中位数

    腾讯一面问到了 用的算法导论中的Kth算法 期望时间复杂度为O n 后来想了想 万一数据多的来根本不能一次读入内存 这个时候该如何解决呢 题目如下 只有2G内存的pc机 在一个存有10G个整数的文件 从中找到中位数 写一个算法 http b