当前位置: 首页 > news >正文

算法通过村第十五关-超大规模|白银笔记|经典问题

文章目录

  • 前言
  • 从40个亿中产生一个不存在的整数
    • 位图存储数据的原理
    • 使用10MB来存储
    • 如何确定分块的区间
  • 用2GB内存在20亿的整数中找到出现次数最多的数
  • 从100亿个URL中查找的问题
  • 40亿个非负整数中找出两次的数。
  • 总结


前言


提示:人生之中总有空白,但有时,我们称它为人生的副歌。在一些或长或短的时间段里,您听不见它,于是以为已经忘记了这段副歌。然后,有一天,在您独自一人,周边又没有什么可以分散注意力的时候,这段副歌忽然又响起来。就像儿歌的歌词,它依旧充满魔力。 --帕特里克·莫迪亚诺《隐形墨水》

理解前面的题目,是不是很难,但是抓住重点理解起来是很容易的,这里再强调一些经典问题(查找

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

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

  • 进阶:如果只有10MB的内存呢,你该怎么处理

这里不用写代码,如果你能将方法说明白,我们看看这里要怎么做。

位图存储数据的原理

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

40亿*4B = 160亿字节,大约需要16GB的空间

40亿/8字节 = 5亿字节,大约需要0.5GB的空间,就可以存储了。

1 字节 = 8 位
1 B(字节)= 8 bit(位)
1 GB(千兆字节)= 1024 MB = 1024 * 1024 KB = 1024 * 1024 * 1024 B

数据量很大,采用位的方式(俗称位图)存储数据是常用的思路,那位图如何存储元素呢?我们可以使用BitMap的方式来表示数出现的情况,具体来说,是申请一个长度位 4295967295 的类型的数组bitArr(就是boolean类型),bitArr上的每一个位置只可以表示0或者1状态,8个bit为1B,所以长度就是 4295967295 的bit数组占用空间为500MB,这样就满足题目要求了。

4294967295 是一个能容纳 40亿个不同数的最小 2 的幂次减 1的值。也就是说,2的32次方(4294967296)可以表示的不同数的个数是40亿,再减去1就得到了4294967295。

那么使用bitArr需要注意什么?就是遍历这40一个数,遇到所有的数时,就把bitArr相对应得位置设置为1.例如遇到1024,就将bitArr[1024] = 1。

遍历完成后,再次遍历bitArr,看看哪个位置上没有被设置为1,这个数就是不存在40亿个数中。当然如果bitArr[5243] == 0,就可以将这个数输出出来。

位存储得核心是:我们存储得并不是这40亿个数据本身,而是其对应得位置。这一点明白就很简单了不是。

使用10MB来存储

如果只有10MB得内存,使用位图就不行了,就需要另辟蹊径了。这里我们采用分块得思想,拿时间换空间,通过两次遍历来搞定。

40亿个数需要500MB得空间,如果只有10MB得空间至少需要50块才可以。

一般来说,我们划分得是使用2得整数倍,因此分成64块最合理。

首先就是将0~4294967295(2^32 -1)这个范围平均分成64个区间,每个区间是67108864个数,例如

  • 第0区间(0~67108863)
  • 第1区间(67108864~134217728)
  • 第i区间(67108864*i~67108864(I+ 1) - 1)
  • 第63区间(4227858432~4294967295)

因为一共40亿个数,所以,如果统计罗在每个区间上得数有多少,肯定有至少一个区间上得计数是小于67108864。利用这一点就可以找出其中一个没有出现过得数,具体过程是通过两次遍历来搞定。

第一次遍历:先申请长度为64得整数数组countArr[0…63],countArr[i]用来统计区间i上得有多少个,遍历40亿个数,根据当前数是多少决定哪个区间上得计数增加。例如67108865,67108865/67108864 = 1,所以第1区间上得计数增加countArr[1]++,遍历完这40亿个数之后遍历countArr,必然会有某个位置上得值(countArr[i]小于67108864,表示第i区间上至少有一个数没有出现过。我们肯定会找到至少一个这样得区间。

此时使用得内存就是countArr的大小(64*4B)是一个非常小的数。

假设找到第37区间上的计数小于67108864,那么我们对这40亿个数据进行第二次遍历

  1. 申请长度为67108864的BitMap,这占用的空间大约是8M,记为bitArr[0…67108863].
  2. 遍历这40亿个数,此时只需要关注落在第37区间上的数,即为num(num 满足 num/67108864 == 37),其他区间的数全部忽略。
  3. 如果步骤2的num在第37区间,将bitArr[num - 67108864*37]的值设置为1,也就是只做第37区间上的数的bitArr映射。
  4. 遍历完40亿个数之后,在bitArr上必然存在没有被设置1的位置,假设第i个位置上面的值没有被设置成1,那么对应的67108864*37 + i,这个数就是没有出现过的数。

总结一下进阶解法:

  1. 根据10MB 的内存限制,确定统计区间的大小,就是第二次遍历时bitArr大小
  2. 利用区间计数的方式,找到那个计数不去的区间,这个区间上肯定有没有出现的数
  3. 对这个区间上的数做bitmap映射,在遍历一遍bitmap,找到一个没有出现的数即可

如何确定分块的区间

上面的例子中,我们可以采用连词遍历,第一次将数据分成64块刚好解决问题。那么我们为什么不是128、32,16或者其他类型呢?

这里主要是保证第二次遍历每块都能放进去10MB的空间中,

2^23 < 10MB < 2 ^ 24,而2^23 = 8388608大约是8MB,也就是说我们依次分块的大小只能为8MB左右,在上面我们也看到了,第二次遍历如果分块是64,刚好满足要求。

所以这里我们最少要分64块,当然如果分成128块,256块也是可以的。

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

题目要求:有一个包含20亿个全是32位整数的大文件,在其中找出出现次数最多的数。

要求:内存限制为2GB

想要在很多整数中找出现次数最多的数,通常的做法是使用哈希表出现的每一个数做词频统计,哈希表的key是某个整数,value是这个整数出现的次数。就本题目来说,一共20亿个数,哪怕只有一个数出现20依次,用32为的整数也是可以便是出现依次而不会产生溢出,所以哈希表的key需要占用4B,value也是4B。那么哈希表中的一条数据就要占用8B,当哈希表中的记录数有20亿时,需要至少1.6GB的内存。

如果20亿个数中不同数超过2亿中,最极端的情况时20亿个数都不同,那么在哈希变种可能要产生20亿条数据,显然这样的内存时不够用的,所以一次性用哈希表统计20亿个数的办法行不通的。

解决办法是把包含20亿个数的大文件用哈希函数分成16个小文件,根基哈希函数的性质,同一种数不能能被散列到不同的小文件上,同时每个小文件中不同的数一定不会找过2亿中,假设哈希函数足够优秀。然后对每一个小文件用哈希表来统计其中每种出现的次数,我们就能得到16个小文件中各自出现最多的数,还有各自的统计次数。接下来就是在个16个小文件各自的第一名相互比较,找到次数最多的那个。

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

从100亿个URL中查找的问题

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

补充题目:某搜索公司一天的用户搜索词汇时海量的(百亿数据量),请设计出一种可以求出每天热门top100词汇的可行办法。

解答:原问题的加法使用解决大数据问题的一种常规套路:把大文件通过哈希函数分配到机器或者通过哈希函数把大文件拆成小文件。一直进行这种划分,直到满足结果要求的资源限制。首先需要确认面试官时候存在资源上限,时间等。在明确限制要求之后,可以将每条URL通过哈希函数分配到若干台机器中或者拆分成小文件。这里的“若干”是由具体的资源限制计算出来的数量。

例如:将100亿字节的大文件通过哈希函数分配到100台机器上面,然后每一台机器分别统计分给自己的URL中是否有重复的URL,同时哈希函数的性质决定了同一条URL不可能分给不同的机器;或者将单机上的大文件通过哈希函数拆分成1000个小文件,对每个小文件再利用哈希表遍历,找出重复的URL;还可以在非给机器差分完后对进行排序,排序后再看看是否有重复的URL出现,总之,牢记一点,很多大数据问题都离不开分流,要么是使用哈希函数将大文件的内容分配给不同的机器;要么是用哈希函数将大文件拆分成小文件,然后处理每个小文件的集合。

补充问题:

最开始还是用哈希分流的思想来处理,把包含百亿数量的词汇文件分流到不同的机器上面,具体多少机器由面试官规定的资源或者给出的限制来决定,对每一台机器来说,如果分到的数据量依然很大的话,比如出现内存不够或者其他问题可以继续使用哈希函数把每台机器的分流文件再次拆分成小文件处理。处理小文件的时候,通过哈希表统计每种词及其频率,哈希表记录建立完成后,在遍历哈希表,遍历哈希表的过程中使用大小为100的小根堆来选出每个小文件的top100(整体未排序的top100)。每一个文件都有自己词频的小根堆,将小根堆的的词按照词频排序,就得到了每个小文件排序后的top100.然后把各个小文件排序后的top100进行外排序或者继续使用小根堆,就可以挑选出每台机器上的top100.不同机器之间的top100在进行外排序或者使用小根堆。最终求出整个百亿数据量中top100**.对于TopK问题,除了使用哈希函数分流和用哈希表做词频统计外,还经常使用堆结构和外排序的手段进行处理。**

40亿个非负整数中找出两次的数。

题目要求:32位无符号整数的范围是0~4294967295,现在又10亿个无符号整数,可以使用最多1GB的内存,找出所有出现了两次的数。

本体可以看看第一题的进阶,这里出现了限制在两次。

首先,可以使用bitmap的方式来表示出现的情况,具体来说,是申请一个长度为4294967295 * 2的bit类型数组bitArr,用2个位置来表示一个数出现的词频,1B占用8bit,所以长度为4294967295 * 2的bit类型的数组占用1GB的空间,那么怎么使用这个bitArr数组呢?遍历这40亿个无符号数,如果初次遇到就把bitArr[num*2]和bitArr[num * 2 ]设置成01,第二次遇到设置成10,第三次遇到设置11.当然以后在遇到就不关系了。遍历完成之后,再次遍历bitArr,如果发现bitArr[i * 2+1]和bitArr[i * 2]设置为10,那么i就是出现两次的数。


总结

提示:大数据的处理方式;海量数据问题;大数据压缩;大数据分块;数据流处理


如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

如有不理解的地方,欢迎你在评论区给我留言,我都会逐一回复 ~

也欢迎你 关注我 ,喜欢交朋友,喜欢一起探讨问题。

在这里插入图片描述

相关文章:

算法通过村第十五关-超大规模|白银笔记|经典问题

文章目录 前言从40个亿中产生一个不存在的整数位图存储数据的原理使用10MB来存储如何确定分块的区间 用2GB内存在20亿的整数中找到出现次数最多的数从100亿个URL中查找的问题40亿个非负整数中找出两次的数。总结 前言 提示&#xff1a;人生之中总有空白&#xff0c;但有时&…...

Mini小主机All-in-one搭建教程6-安装苹果MacOS系统

笔者使用的ESXI7.0 Update 3 抱着试试的态度想安装一下苹果的MacOS系统 主要步骤有2个 1.解锁unlocker虚拟机系统 2.安装苹果MacOS系统 需要下载的文件 unlocker 这一步是最耗时间的&#xff0c;要找到匹配自己系统的unlocker文件。 https://github.com/THDCOM/ESXiUnloc…...

Android中使用Glide加载圆形图像或给图片设置指定圆角

一、Glide加载圆形头像 效果 R.mipmap.head_icon是默认圆形头像 ImageView mImage findViewById(R.id.image);RequestOptions options new RequestOptions().placeholder(R.mipmap.head_icon).circleCropTransform(); Glide.with(this).load("图像Uri").apply(o…...

Nginx 代理

目录 正向代理 反向代理 负载均衡 负载均衡的工作原理 优势和好处 算法和策略 应用领域 Nginx 的反向代理 应用场景 在网络通信中&#xff0c;代理服务器扮演着重要的角色&#xff0c;其中正向代理和反向代理是两种常见的代理服务器模式。它们在网络安全、性能优化和…...

uniapp(uncloud) 使用生态开发接口详情4(wangeditor 富文本, 云对象, postman 网络请求)

wangeditor 官网: https://www.wangeditor.com/v4/pages/01-%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8/01-%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8.html 这里用vue2版本,用wangeditor 4 终端命令: npm i wangeditor --save 开始使用 在项目pages > sy_news > add.vue 页面中…...

Halcon 中查看算子和函数的执行时间

1、在Halcol主窗口的底栏中的第一个图标显示算子或函数的执行时间&#xff0c;如下图&#xff1a; 2、在Halcon的菜单栏中选择【窗口】&#xff0c;在下拉框中选择【打开输出控制台】&#xff0c;进行查看算子或函数的执行时间&#xff0c;如下图&#xff1a;...

Python中的With ...as... 作用

Python中的with … as …作用&#xff1a; 1、通过with语句可以得到一个上下文管理器 2、执行对象 3、加载__enter__方法 4、加载__exit__方法 5、执行__enter__方法 6、as 可以得到enter的返回值 7、拿到对象执行相关操作 8、执行完了之后调用__exit__方法 9、如果遇到异常&a…...

腾讯云国际站服务器如何打开音频设备?

在使用腾讯云服务器进行音频处理或直播等活动时&#xff0c;或许需求翻开服务器的音频设备。本文将详细介绍如安在腾讯云服务器上翻开音频设备。 在腾讯云服务器上翻开音频设备的过程如下&#xff1a; 登录腾讯云服务器办理控制台 1.首先&#xff0c;需求登录腾讯云服务器的办理…...

k8s day05

上周内容回顾: - 基于kubeadm部署k8s集群 ***** - Pod的基础管理 ***** 是K8S集群中最小的部署单元。 ---> 网络基础容器(pause:v3.1)&#xff0c;提供网络 ---> 初始化容器(initContainer)&#xff0c;做初始化的准备工作…...

微信小程序里报名链接怎么做

微信小程序是一种便捷、实用的应用程序&#xff0c;它依托于微信平台&#xff0c;无需下载安装即可使用。在小程序中&#xff0c;我们可以制作报名链接&#xff0c;以便用户直接在微信中进行报名操作&#xff0c;提高服务效率。下面我们将探讨如何制作微信小程序里的报名链接为…...

Kotlin中的逻辑运算符

在Kotlin中&#xff0c;逻辑运算符用于对布尔值进行逻辑运算。Kotlin提供了三个逻辑运算符&#xff1a;与运算&#xff08;&&&#xff09;、或运算&#xff08;||&#xff09;和非运算&#xff08;!&#xff09;。下面对这些逻辑运算符进行详细介绍&#xff0c;并提供示…...

启智平台新建一个调试任务后,如何配环境,并提交镜像

1. 选一个基础版的镜像&#xff0c;我选的是第一个 2. 点击“调试”&#xff0c;进入调试页面 3. 输入bash&#xff0c;再输入pip list 就可以看到镜像自带的conda中已经安装的包 &#xff01;注意&#xff0c;这里一进入到调试页面&#xff0c;不要输入su&#xff0c;一定要…...

模糊测试面面观 | 车联网场景模糊测试解决方案

随着国际国内汽车信息安全标准的出台、用户安全意识的不断提高以及针对智能网联汽车安全攻击的不断规模化复杂化和深入&#xff0c;智能网联汽车系统及车联网安全形势严峻。 然而大部分车型在信息安全防护方面水平偏低&#xff0c;车内相关的联网部件及控制部件防护可靠性不高&…...

超声波清洗机有没有平价又好用的推荐、平价好用超声波清洗机总结

超声波清洗机以其高效、环保、节能等优点在日常生活中得到了广泛应用。无论是在珠宝首饰、眼镜等小物品的清洁方面&#xff0c;还是在医疗领域的清洁消毒方面&#xff0c;超声波清洗机都发挥着不可替代的作用。在购买超声波清洗机时&#xff0c;需要根据自己的具体需求选择合适…...

工控机通过485modbus转profinet网关与温度智能表通讯配置案例

在这个案例中&#xff0c;通过485modbus转profinet网关&#xff08;XD-MDPN100&#xff09;可以实现工控机与温度智能表之间的双向通信。工控机通过modbus协议将温度数据发送到网关&#xff0c;网关将数据转换为profinet协议后发送给温度智能表进行显示和控制。 通过485modbus转…...

【网络】计算机网络基础概念入门

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;个人主页 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#…...

Node.js的crypto模块 加密

Node.js的crypto模块提供了许多加密和解密功能&#xff0c;包括对称加密、非对称加密、哈希函数等。在本篇文章中&#xff0c;我们将详细介绍Node.js的crypto模块的API、代码注释和举例。 加密和解密 对称加密 对称加密算法使用相同的密钥进行加密和解密&#xff0c;例如AES…...

react+hooks使用

参考视频&#xff1a;https://www.bilibili.com/video/BV1ZB4y1Z7o8/?p3&spm_id_frompageDriver&vd_source5c584bd3b474d579d0bbbffdf0437c70 1.快速搭建开发环境 create-react-app是一个快速 创建react开发环境的工具&#xff0c;底层由webpack构建&#xff0c;封装…...

wsl2安装fsl

按照教程安装完毕之后&#xff0c;终端输入命令glxgears判断vcxsrv是否可用若有三个轮子即可用&#xff0c; 然后将三个齿轮关闭&#xff0c;并将vcxsrv挂起&#xff0c;使用Ubuntu终端输入 sudo gedit /etc/profile 打开写字板&#xff0c;&#xff08;此时写字板是会出现在vc…...

mac电脑zsh: command not found: adb

“zsh: command not found: adb” 的解决方法&#xff1a; 前提 已经成功安装了 Android Studio. 打开 iTerm 终端依次输入下面命令&#xff1a; echo export ANDROID_HOME/Users/$USER/Library/Android/sdk >> ~/.zshrc echo export PATH${PATH}:$ANDROID_HOME/tool…...

GitHub下载太慢的解决方案

修改hosts文件&#xff1a; windows的hosts文件在 C:\Windows\System32\drivers\etc\hosts cmd管理员运行命令notepad C:\Windows\System32\drivers\etc\hosts 然后cmd命令重启网络ipconfig /flushdns windows修改hosts Ubuntu22.04修改hosts sudo vim /etc/hosts # This fil…...

英语生活常用词,柯桥成人零基础英语培训

Shopping mall 商场 - elevator 升降电梯 - men’s clothing department 男装部 - mannequin 人体模特 - fitting room 试衣间 - display counter 陈列柜 - women’s clothing department 女装部 - price tag 价标 - cosmetics department 化妆品专柜 - salesclerk 销售…...

【前端学习】—使用多种方式实现数组去重(六)

【前端学习】—使用多种方式实现数组去重(六) 一、数组常用的几个方法 //[1,2,3,4,2,1]//[{name:"caicai",age:"10"},{name:"zhangsan",age:"20"}]const array=[...

JAVACPU占用过高、内存泄漏问题排查

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…...

2023年【公路水运工程施工企业安全生产管理人员】新版试题及公路水运工程施工企业安全生产管理人员模拟试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 公路水运工程施工企业安全生产管理人员新版试题是安全生产模拟考试一点通生成的&#xff0c;公路水运工程施工企业安全生产管理人员证模拟考试题库是根据公路水运工程施工企业安全生产管理人员最新版教材汇编出公路水…...

屏幕截图软件Snagit 2023 mac中文特点介绍

Snagit 2023 mac是一款屏幕截图和视频录制软件&#xff0c;它可以帮助用户快速捕捉屏幕上的任何内容&#xff0c;并将其编辑、标注和共享。 Snagit 2023 软件特点 多种截图模式&#xff1a;支持全屏截图、窗口截图、区域截图、延时截图等多种截图模式&#xff0c;满足不同用户…...

deepin操作系统下载

官网 最新版本 – 深度科技社区 下载页面 最新版本 – 深度科技社区 随便选择一个下载 直接下载地址 https://cdimage.deepin.com/releases/20.9/deepin-desktop-community-20.9-amd64.iso...

【docker】查看容器日志

目录 一.通过查找宿主机日志路径&#xff0c;通过Linux命令查看即可。 1.1 查看容器日志路径 1.2 按照日志路径检索日志 二、通过docker命令检索日志 2.1 查看指定时间后的日志&#xff0c;只显示最后20行 2.2 查看最近10分钟的日志 2.3 查看某时间段之后的日志 2.4 查…...

Vue使用Echarts建立知识图谱

文章目录 一、安装Echarts二、main.js中引入Echarts三、封装成组件四、渲染结果一、安装Echarts npm install echarts@4.9.0二、main.js中引入Echarts // 引入echarts --------------------- // npm install echarts@4.9.0 import echarts from echarts Vue.prototype.$echar…...

力扣(LeetCode)1726. 同积元组(C++)

哈希表 请看示例&#xff0c;可发现规律&#xff1a;乘积相同的两个数对&#xff0c;存在8种排列&#xff0c;满足同积元组的要求。于是有结论&#xff1a;乘积相同的两个数对&#xff0c;对答案的贡献是ansans8. 如上所述&#xff0c;我们需要先知道数对的乘积&#xff0c;才…...