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

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

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java】详解多线程的概述及三种创建方法

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;Java ⭐每日一句&#xff1a;身在井隅&#xff0c;心向阳光&#xff0c;眼里有诗&#xff0c;自在远方 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4…

【JVM系列】- 寻觅·方法区的内容

寻觅方法区的内容 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录 寻觅…

Pyside6/PYQT6如何实现无边框设计,解决无边框窗口无法移动的问题

文章目录 💢 问题 💢💯 解决方案 💯🍔 准备工作🐾 操作步骤🐾 窗口无边框🐾 窗口透明🐾 实现窗口可移动⚓️ 相关链接 ⚓️💢 问题 💢 有时候我们需要一个无边框的UI设计来实现/美化一些功能,如:制作一个桌面时钟,进度条展示等,要实现无边框其实很简…

【 第十一章】软件设计师 之 面向对象设计与结构化分析设计

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 备考资料导航 软考好处&#xff1a;软考的…

【Proteus仿真】【Arduino单片机】LCD1602液晶显示

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602液晶显示各种效果。 二、软件设计 /* 作者&#xff1a;嗨小易&#x…

MSF图形化工具Viper快速安装

简介 Viper(炫彩蛇)是一款图形化内网渗透工具,将内网渗透过程中常用的战术及技术进行模块化及武器化. Viper(炫彩蛇)集成杀软绕过,内网隧道,文件管理,命令行等基础功能. Viper(炫彩蛇)当前已集成70个模块,覆盖初始访问/持久化/权限提升/防御绕过/凭证访问/信息收集/横向移动等…

【MySQL系列】 第二章 · SQL(下)

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

保姆级jupyter lab配置清单

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

通过SD卡给某摄像头植入可控程序

0x01. 摄像头卡刷初体验 最近研究了手上一台摄像头的sd卡刷机功能&#xff0c;该摄像头只支持fat32格式的sd卡&#xff0c;所以需要先把sd卡格式化为fat32&#xff0c;另外微软把fat32限制了最大容量32G&#xff0c;所以也只能用不大于32G的sd卡来刷机。 这里使用32G的sd卡来…

09 # 手写 some 方法

some 使用 some() 方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。如果在数组中找到一个元素使得提供的函数返回 true&#xff0c;则返回 true&#xff1b;否则返回 false。它不会修改数组。 ele&#xff1a;表示数组中的每一个元素index&#xff1a;表示数…

Unity中Shader的雾效

文章目录 前言一、Unity中的雾效在哪开启二、Unity中不同种类雾的区别1、线性雾2、指数雾1&#xff08;推荐用这个&#xff0c;兼具效果和性能&#xff09;3、指数雾2&#xff08;效果更真实&#xff0c;性能消耗多&#xff09; 三、在我们自己的Shader中实现判断&#xff0c;是…

vue设计原理-带你重走vue诞生路程

我们首先看下面这个小demo demo源码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conten…

RT-DETR 应用 CARAFE:特征内容感知重新组装

特征上采样是现代卷积神经网络架构中的关键操作,例如特征金字塔。其设计对于密集预测任务,如目标检测和语义/实例分割至关重要。在本研究中,我们提出了一种称为内容感知特征重组(CARAFE)的通用、轻量级且高效的操作符,以实现这一目标。CARAFE具有以下几个优点:(1)大的…

算法通关村第七关-青铜挑战二叉树的深度优先遍历(递归)

二叉树的深度优先遍历 今天我们来说二叉树的深度优先遍历 , 这次用简单但有点难理解的方式递归来实现 , 对应LeetCode 144,145 二叉树的前序遍历 描述 : 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 题目 : LeetCode 二叉树的前序遍历 : 144. 二叉…

【FAQ】Gradle开发问题汇总

1. buildSrc依赖Spring Denpendency时报错 来自预编译脚本的插件请求不能包含版本号。请从有问题的请求中删除该版本&#xff0c;并确保包含所请求插件io.spring.dependency-management的模块是一个实现依赖项 解决方案 https://www.5axxw.com/questions/content/uqw0grhttps:/…

K8S知识点(九)

&#xff08;1&#xff09;Pod详解-结构和定义 一级属性有下面这些&#xff1a;前两个属性是字符串&#xff0c;上面有定义 kind&#xff1a;Pod version&#xff1a;v1 下面的属性是object 还可以继续查看子属性&#xff1a;二级属性 还可以继续查看三级属性&#xff1a; 通…

微软近日限制员工访问ChatGPT!

作者 | 撒鸿宇 据CNBC报道&#xff0c;在这周四的短时间内&#xff0c;微软的员工被禁止使用ChatGPT。 微软在其内部网站的更新中表示&#xff1a;“由于安全和数据问题&#xff0c;一些AI工具不再对员工开放。”据CNBC查证&#xff0c;他们看到了一张截图&#xff0c;该截图显…

KubeSphere 社区双周报 | KubeSphere 3.4.1 发布 | 2023.10.27-11.09

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.10.27-2023.…

Nuxt.js——基于 Vue 的服务端渲染应用框架

文章目录 前言一、知识普及什么是服务端渲染什么是客户端渲染&#xff1f;服务端渲染与客户端渲染那个更优秀&#xff1f; 二、Nuxt.js的特点Nuxt.js的适用情况&#xff1f; 三、Vue是如何实现服务端渲染的&#xff1f;安装依赖使用vue安装 Nuxt使用npm install安装依赖包使用n…

UE特效案例 —— 角色刀光

目录 一&#xff0c;环境配置 二&#xff0c;场景及相机设置 三&#xff0c;效果制作 刀光制作 地裂制作 击打地面炸开制作 一&#xff0c;环境配置 创建默认地形Landscape&#xff0c;如给地形上材质需确定比例&#xff1b;添加环境主光源DirectionalLight&#xff0c;设…