算法通关村第十五关白银挑战——海量数据场景下的热门算法题

大家好,我是怒码少年小码。

最近超级忙,很多实验报告,已经四五天没搞了,但是我还是回来了!

海量数据场景下的热门算法题

本篇的题目不要求写代码,面试的时候能很清楚的说出思路就可以了。

1. 从40个亿中产生一个不存在的整数

题目要求:给定一个输入文件,包含40亿个非负整数,设计一个算法,产生一个不存在该文件的整数,假设你有1GB的内存来完成这项任务

进阶:如果只有10MB的内存可用,该怎么办

位图存储大数据的原理

假设用哈希表来保存出现过的数,如果40亿个数都不同,则哈希表的记录数为40亿条,存一个32位整数需要4B,所以最差情况需要40亿 * 4B = 160亿字节,大约需要16GB的空间,不符合要求

  • 40亿 * 4B = 160 亿字节,大约需要16GB
  • 40亿 / 8字节 = 5亿字节,大约0.5GB的数组就可以存下40亿个

如果数据量很大,采用位方式(俗称位图)存储数据是常用的思路。
我们使用bit map(比特数组)的方式来表示数出现的情况。即申请一个长度为4294967 295的bit类型的数组bitArr(就是boolean类型),bitArr上的每个位置只可以表示0 或 1状态。8个bit 为1B,所以长度为4294967 295的bit 类型的数组占用5000MB空间,满足题目给定的要求

使用bitArr数组的方法:遍历40亿个无符号数,遇到所有的数时,就把bitArr相应位置的值设置为1。例如,遇到1000,就把bitArr[1000]设置为1
遍历完成后,再依次遍历bitArr数组,看看哪个位置上的值没被设置为1,这个数就不在40亿个数中。例如,发现bitArr[8001] == 0,那么8001就是没出现过的数,遍历完bitArr之后,所有没出现的数就都没出来了。

位存储的核心是:存储的并不是这40亿个数据本身,而是其对应的位置。

进阶:使用10MB来存储

如果只有10MB内存,位图也不能完成。使用分块思想,时间换空间,通过两次遍历完成
40亿个数采用位图至少需要0.5GB空间,如果只有10MB空间,也至少需要50个块
一般来说,划分都是使用2的整数倍,因此划分成64个块比较合理

一共只有40亿个数,所以,如果统计落在每一个区间上的数有多少,肯定有至少一个区间上的计数少于67 108 864(2^32 / 64)。利用这个可以找出其中一个没出现的数。

  1. 如果当前数是 3422552090, 3422552090 / 67 108 864 = 51,所以第51区间上的计数增加countArr[51]++。

  2. 遍历完40亿个数之后,遍历countArr,必然会有某一个位置上的值(countArr[i])小于67 108 864,表示第 i 区间上至少有一个数没出现过。此时使用的内存就是countArr的大小(64 * 4B),占用的空间非常小

  3. 假设找到第37区间上的计数小于67 108 864(知道哪些区间计数小于67 108 864计数),然后对40亿个数据进行第二次遍历

  • 申请长度为67 108 864的bit map(比特数组),占用大约8MB空间,记为bitArr[0…67 108 864]
  • 遍历这40亿个数,此时的遍历只关注落在第37区间上的数,记为num (num满足num / 67 108 864 == 37),其他区间的数全部忽略
  • 如果步骤2的num在第37区间上,将bit[num - 67 108 864 * 37]的值设置为1,也就是只做第37区间上的数bitArr映射(通过相减可以得到在bit数组的位置i)
  • 遍历完40亿个数之后,在bitArr上必然存在没被设置成1的位置,假设第i个位置上的值没设置成1,那么67 108 864* 37 + i这个数就是一个没出现过的数
总结:
  1. 根据10MB的内存限制,确定统计区间的大小,就是第二次遍历时的bitArr大小
  2. 利用区间计数的方式(用countArr[i]++),找到那个计数不足的区间,这个区间上肯定有没出现的数
  3. 对这个区间上的数做bit map映射,再遍历bit map(bit数组),找到一个没出现的数即可
如何确定分块的区间

针对上面例子中分块大小为64块的问题,为什么不是128块、32块、16块或其他类型
主要保证第二次遍历时每个块都能放进这10MB的空间。223<10MB<224,而2^23占用大约为8MB空间,也就是说一次的分块大小只能为8MB左右。上面的第二次遍历时如果分为64块,则刚好满足要求。
所以这里最少要分成64块,如果分成128块、256块也可以。

2. 用2GB内存在20亿个整数中找到出现次数最多的数

题目要求:有一个包含20亿个全是32位整数的大文件,在其中找到出现次数最多的数(内存限制为2GB)

思路分析:

通常在很多整数中找到出现次数最多的数,常见是使用哈希表对出现的每一个数做词频统计,哈希表的key是某一个整数,value是这个数出现的次数。

但是就这题来说,一共有20亿个数,哈希表一条记录(key,value)需要8B,当哈希表记录数为2亿个时,需要至少1.6GB内存,当出现极端情况,20亿个数都不同,内存会不够用

解决方法:

把包含20亿个数的大文件用哈希函数分成16个小文件,根据哈希函数的性质,同一种数不可能被散列到不同的小文件上,同时每个小文件中不同的数一定不会大于2亿种。假设哈希函数足够优秀,然后对每一个小文件用哈希表来统计每种数出现的次数,这样就得到了16个小文件中各自出现次数最多的数和各自次数统计,接下来再进行比较即可。

总结:

把一个大的集合通过哈希函数分配到多台机器中,或者分配到多个文件里,这种技巧是在处理大数据面试题最常用技巧之一。
但是到底分配到多少台机器、分配到多少个文件,在解题时一定要确定下来。可能在与面试官沟通过程中由面试官指定,也可能是根据具体的限制来确定,比如本题确定分成16个文件,就是根据内存限制2GB的条件来确定。

3. 从100亿个URL中查找的问题

题目要求:有一个包含100亿个URL的大文件,假设每个URL占用64B,请找出其中所有重复的URL

补充问题:某搜索公司一天的用户搜索词汇是海量的(百亿数据量),请设计一种求出每天热门 Top 100词汇的可行方法)

解答:

原问题的解法使用解决大数据问题的一种常规方法:把大文件通过哈希函数分配到机器,或者通过哈希函数把大文件拆成小文件,一直进行这种划分,直到划分的结果满足资源限制的要求。

  1. 首先要向面试官询问在资源上的限制有哪些,包括内存、计算时间等要求
  2. 明确限制要求之后,可以将每条URL通过哈希函数分配到若干台机器或者拆分成若干个小文件(这里的"若干"由具体的资源限制来计算出精确的数量)
补充问题:

最开始还是用哈希分流的思路来处理,把包含百亿数据量的词汇文件分流到不同的机器上,具体多少台机器由面试官规定或者由更多的限制来决定。

  1. 对每一台机器来说,如果分到的数据量依然很大,比如,内存不够或存在其他问题,可以再用哈希函数把每台机器的分流文件拆成更小的文件处理。
  2. 处理每一个小文件的时候,通过哈希表统计每种词及其词频,哈希表记录建立完成后,再遍历哈希表
  3. 遍历哈希表的过程中使用大小为100的小根堆来选出每一个小文件的Top 100(整体未排序的Top 100)。
  4. 每一个小文件都有自己词频的小根堆(整体未排序),将小根堆里的词按照词频排序,就得到了每个小文件的排序后Top 100。
  5. 然后把各个小文件排序后的Top 100进行外排序或者继续利用小根堆,就可以选出每台机器上的Top 100。同理,不同机器之间的Top 100再进行外排序或者继续利用小根堆,最终求出整个百亿数据量中的Top 100。

对于Top K的问题,除用哈希函数分流和用哈希表做词频统计之外,还经常用堆结构和外排序的手段进行处理。

例如:
  1. 将100亿字节的大文件通过哈希函数分配到100台机器上,然后每一台机器分别统计分给自己的URL中是否有重复的URL,同时哈希函数的性质决定了同一条URL不可能分给不同的机器;
  2. 或者在单机上将大文件通过哈希函数拆成1000个小文件,对每一个小文件再利用哈希表遍历,找出重复的URL;
  3. 还可以在分给机器或拆完文件之后进行排序,排序过后再看是否有重复的URL出现。
总结:

很多大数据问题都离不开分流

  • 用哈希函数把大文件的内容分配给不同的机器
  • 用哈希函数把大文件拆成小文件
  • 用哈希函数把大文件拆成小文件,然后处理每一个小数量的集合

4. 40亿个非负整数中找到出现两次的数

题目要求:32位无符号整数的范围是0 ~ 4294967295,现在有40亿个无符号整数,可以使用最多1GB的内存,找出所有出现了两次的数
(这题可以看作第一题的进阶问题,将出现次数限制在了两次)

解题思路:
  1. 可以用bit map的方式表示数出现的情况。具体就是申请一个长度为 4294967295 * 2的bit类型的数组bitArr,用两个位置表示一个数出现的词频,1B占用8个bit,所以长度为4294967295 * 2的bit类型数组占用1GB空间

  2. 使用方法:遍历这40亿个无符号数

  • 如果初次遇到num,就把bitArr[num * 2 + 1]和bitArr[num * 2]设置为01
  • 如果第二次遇到num,就把bitArr[num * 2 + 1]和bitArr[num * 2]设置为10
  • 如果第三次遇到num,就把bitArr[num * 2 + 1]和bitArr[num * 2]设置为11
  • 以后再遇到num,发现此时bitArr[num * 2 + 1]和bitArr[num * 2]已经被设置为11,就不再做任何设置。
  • 遍历完成后,再依次遍历bitArr,如果发生bitArr[num * 2 + 1]和bitArr[num * 2]设置为10,那么i就是出现了两次的数

END

看得很枯燥无味~但是!加油!!

参考文章1:https://juejin.cn/post/7288229413034999866
转载文章1:https://cv3c20a1rv4.feishu.cn/wiki/DViewhOX9iSxCAkmvHGcxxMsnRd

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/140349.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RESTful API概述以及如何使用它构建 web 应用程序

REST&#xff08;Representational State Transfer&#xff09;是一种设计风格和架构原则&#xff0c;它是一种为 Web 应用程序提供简化和标准化的 API 的方式。RESTful API&#xff08;RESTful Web Services&#xff09;是符合 REST 架构风格的网络应用程序 API&#xff0c;它…

SpringBoot学习笔记-项目初始化

笔记内容转载自 AcWing 的 SpringBoot 框架课讲义&#xff0c;课程链接&#xff1a;AcWing SpringBoot 框架课。 CONTENTS 1. 概念与项目介绍2. 创建SpringBoot项目后端3. 前后端不分离开发方式4. 前后端分离开发方式5. 创建Vue项目前端6. 前后端通信 1. 概念与项目介绍 本次开…

RSA加密、解密、签名、验签(验证签名)RSA算法原理

一、加密的原因 1.加密&#xff1a;是为了防止信息泄露&#xff1b; 2.签名&#xff1a;签名为了防止信息被篡改&#xff0c;保证数据完整性和发送方角色的可靠性和不可依赖性。 二、RSA加密简介 RSA加密是一种非对称加密。可在不直接传递密钥的情况下&#xff0c;完成解密&…

如何解决Windows电脑 Create folder error,Access is denied.

如何解决 Create folder error, Error: mkdir C:\Program Files\nodejs\21.1.0/: Access is denied. Waring: Name : http://npm.taobao.org/mirrors/node/v21.1.0/win-x64/node.exe Code : -2 Error : Create folder error, Error: mkdir C:\Program Files\nodejs\\21.1.0/…

【Vue原理解析】之模版编译

引言 Vue.js是一款流行的JavaScript框架&#xff0c;它采用了基于组件的开发模式&#xff0c;使得前端开发更加简单和高效。而Vue的核心功能之一就是模版解析&#xff0c;它负责将Vue组件中的模版代码转化为可执行的JavaScript代码。本文将深入探讨Vue模版解析的作用、核心源码…

【文末送书】如何在时间循环里最优决策?

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

OpenAI调查ChatGPT故障;向量搜索的优势与局限

&#x1f989; AI新闻 &#x1f680; OpenAI调查ChatGPT故障&#xff0c;发布新AI产品GPTs和GPT-4 Turbo 摘要&#xff1a;OpenAI的ChatGPT和其他服务出现故障&#xff0c;经过调查后发现是由于DDoS攻击导致的异常流量模式。OpenAI在首届开发者大会上发布了新的AI产品GPTs&am…

CSS3 2D、3D转换

一、CSS3 2D转换&#xff1a; CSS3转换可以对元素进行移动、缩放、转动、拉长或拉伸。 2D变换的方法&#xff1a;translate()、rolate()、scale()、skew()、matrix()。 <style> div { width:200px; height:100px; background-color:red; /* Rotate div */ tran…

Linux命令(120)之tcpdump

linux命令之tcpdump 1.tcpdump介绍 linux命令tcpdump是用来将网络中传送的数据包完全截获下来以进行相关分析&#xff0c;常用的分析工具是wireshark 2.tcpdump用法 tcpdump [参数] tcpdump参数 参数说明-i指定端口-n指定协议-t在输出的每一行不打印时间戳-s抓取数据包时&a…

酷柚易汛ERP - 发货地址管理操作指南

1、应用场景 对发货地址进行管理&#xff0c;使用【物流服务】时的自动获取发货地址。 2、主要操作 打开【资料】-【发货地址管理】新增发货地址。 可以对进行地址设置及管理&#xff0c;点击【新增】可添加新的发货地址信息地址简称方便使用者在选择发货地址时&#xff0c;…

Spring集成MyBatis(自定义类和xml配置文件两种形式)

将mybatis与spring进行整合&#xff0c;主要解决的问题就是讲SqlSessionFactory对象交由spring来管理&#xff0c;所以&#xff0c;该整合&#xff0c;只需要将SqlSessionFactory的对象生成器SqlSessionFactoryBean注册在spring容器中&#xff0c;再将其注入给Dao的实现类即可完…

Lambertian模型(完美漫反射)

这里使用相乘的方式组合光照色和纹理色。根据这个模型,面朝光源的区域光照强度高,纹理色也相应增强。面背光源的区域光照弱,纹理色也被抑制。这样通过光照和纹理的结合,可以合成出具有照明效果的面部颜色,而不仅仅是固定的纹理本身的颜色。相乘方式可以近似实现不同光照方向下面…

TCP怎么实现可靠传输

链接 1&#xff0c;TCP头部的校验和保证获取正确数据&#xff0c;防篡改&#xff1b; 2&#xff0c;序列号和ACK确认机制同于管理数据包&#xff0c;对接收到的数据包进行确认&#xff0c;对没有接收到的数据包进行重传&#xff1b; 3&#xff0c;重传机制&#xff0c;包括超…

MongoDB副本集配置和创建

副本集有三类角色&#xff1a;master(primary)&#xff0c;slave(secondary)&#xff0c;仲裁服务器。 primary是主&#xff0c;只有primary能写入&#xff0c;secondary无法插入数据&#xff0c;且需要声明是slave才能查看数据 一般生产搞三个服务器做一个master和两个slave&a…

树状数组:leetcode307 区域和检索

307. 区域和检索 - 数组可修改 给你一个数组 nums &#xff0c;请你完成两类查询。 其中一类查询要求 更新 数组 nums 下标对应的值另一类查询要求返回数组 nums 中索引 left 和索引 right 之间&#xff08; 包含 &#xff09;的nums元素的 和 &#xff0c;其中 left < ri…

成都优优聚美团代运营:打造高效电商运营的利器

一、引人注目的标题 在繁杂的电商市场中&#xff0c;成都优优聚美团代运营以其专业的服务&#xff0c;为商家提供了一站式的解决方案。那么&#xff0c;这个备受瞩目的代运营平台有何特别之处呢&#xff1f;今天&#xff0c;我们就来一探究竟。 二、平台背景与优势 成都优优聚…

前端如何把图片url地址https://url转成base64

前端如何把图片url地址https://url转成base64 一、直接上代码 一、直接上代码 async getImgImg() {let url await this.base64(this.From.imageData) }&#xff0c; base64(url) {return new Promise(resolve > {const image new Image()// 先设置图片跨域属性image.cros…

JL-03小型气象站气象环境在线监测设备自动上传并保存数据

JL-03小型气象站产品概述 小型气象站用于对风速、风向、雨量、空气温度、空气湿度、太阳辐射、光照强度、土壤温度、土壤湿度、蒸发量、大气压力等气象要素进行现场监测。既可以通过无线通讯将数据传送至云平台&#xff0c;又可以通过配套的数据采集通讯线与计算机进行连接&am…

C/C++内嵌简本语言-LUA

一、LUA简介 Lua [1] 是一个小巧的脚本语言。Lua脚本可以很容易的被C/C 代码调用&#xff0c;也可以反过来调用C/C的函数&#xff0c;这使得Lua在应用程序中可以被广泛应用。不仅仅作为扩展脚本&#xff0c;也可以作为普通的配置文件&#xff0c;代替XML,ini等文件格式&#…

1. 深度学习——激活函数

机器学习面试题汇总与解析——激活函数 本章讲解知识点 什么是激活函数&#xff1f; 为什么要使用激活函数&#xff1f; 详细讲解激活函数 本专栏适合于Python已经入门的学生或人士&#xff0c;有一定的编程基础。本专栏适合于算法工程师、机器学习、图像处理求职的学生或人…