【C++】海量数据面试题

news2024/9/20 19:27:30

海量数据面试题

在这里插入图片描述

文章目录

  • 海量数据面试题
  • 一、哈希切割
  • 二、位图应用
    • 1.给定100亿个整数,设计算法找到只出现一次的整数
    • 2.求两个文件交集
    • 3.在100亿个整数中找到出现次数不超过2次的所有整数
  • 三、布隆过滤器
    • 1.求两文件交集(近似算法)
    • 2.求两文件交集(精确算法)
    • 3.计数法使布隆过滤器支持删除

一、哈希切割

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

  • 我们可以把这100G大小的文件切分成100个小文件
  • 依次读取ip地址,通过哈希函数把每个ip地址转换为一个整型,再把这些分别%100切分到这100个小文件里头

image-20230413232452174

  • 此时相同的ip地址通过哈希函数转换的整型一定是相同的,最终也一定进入同一个文件,不同的ip也可能进入同一个文件,现在我们使用map容器(map<string, int> countMap)依次对每个小文件统计次数,统计完A0,把A0的次数记录下来为最大次数(pair<ip, int> maxIP),clear旧数据,再统计A1,比较A1的次数和最大次数的大小,更新最大次数,再clear掉旧数据……,依次比较,依次更新最大次数的数据。
  • 如果需要找到top K,就需要用到优先级队列(priority_queue<pair<string,int>,vector<pair<string,int>>,less>),less仿函数将比较pair中int的大小,使用小堆可满足找最大的K个值的条件。

使用上述哈希切割的方法可以找到出现次数最多的IP地址,但是会存在一个小问题:某个文件太大,导致某个相同ip太多,且映射冲突到这个编号文件的ip太多(可能又会导致内存不够了),这里我们可以try-catch捕获,伪代码如下:

try
{
	countMap[ip]++;
}
catch (exception& e)
{
	//捕获内存不足的异常,说明内存不够
	countMap.clear();
	//针对这个小文件,再次换个哈希函数,进行哈希切分,再切分成小文件
	//再对小文件依次统计
}

找到topK的Linux的指令如下:

假如有以下文件IP.log:

192.168.5.5
234.23.13.44
10.152.16.23
192.168.3.10
192.168.1.4
192.168.2.1
192.168.0.9
10.152.16.23
192.163.0.9
192.168.0.9 
69.52.220.44 
192.168.1.4 
192.168.1.5
192.163.0.9 
192.168.2.1
192.168.0.1
192.168.0.2

(1)按行排序,并将结果输出到标准输出

sort 文件名

(2)统计并显示文本文件中出现的行或列的次数

uniq -c

(3)根据出现次数倒序排序

sort -r

(4)查看开头K行

head -k

综上:显示出现次数最多的前K个IP

sort log_file | uniq -c | sort -nr | head -k

sort log_file对文件进行排序,使得相同的IP地址聚在一起,接着使用uniq -c进行去重,并将重复的次数显示在每列的旁边,通过这个次数来使用sort -nr进行降序排序,使得出现次数最高的IP地址在前面,然后使用head -k获取前k个IP地址。

运行结果:

image-20230420200321294

image-20230420200346809


二、位图应用

1.给定100亿个整数,设计算法找到只出现一次的整数

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

题目明确说找到只出现一次的整数,那说明一个整数出现的次数的情况分为如下三种状态:

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

一个比特位只能表示一种状态,但是两个比特位就能表示4种了,因此我们借助两个比特位来表示如上三种状态:

  • 00(0次)
  • 01(1次)
  • 10(2次)

所以这里我们需要重新写一个位图,两个比特位表示一个值,所以一个char只能表示4个值(8bit / 2),100亿个整数要开2^32 * 2个比特位,大概占1G。

image-20230413162344031

虽然这里是两个比特位表示一个值,不过我们实际操作的时候可以设计一个类,里面封装两个bitset,并且通过后续的位运算来表示两个比特位表示一个值。

image-20230413233702278

具体实现的代码如下:

template<size_t N>
class twobitset
{
public:
	void set(size_t x)
	{
		if (!_bs1.test(x) && !_bs2.test(x)) // 00
		{
			_bs2.set(x); // 01
		}
		else if (!_bs1.test(x) && _bs2.test(x)) // 01
		{
			_bs1.set(x); 
			_bs2.reset(x); // 10
		}

		// 10 不变
	}

	void PirntOnce()
	{
		for (size_t i = 0; i < N; ++i)
		{
			if (!_bs1.test(i) && _bs2.test(i))
			{
				cout << i << endl;
			}
		}
		cout << endl;
	}
private:
	bitset<N> _bs1;
	bitset<N> _bs2;
};

简易测试代码如下:

void test_twobitset()
{
	twobitset<100> tbs;
	int a[] = { 3, 5, 6, 7, 8, 9, 33, 55, 67, 3, 3, 3, 5, 9, 33 };
	for (auto e : a)
	{
		tbs.set(e);
	}
	tbs.PirntOnce();
}

2.求两个文件交集

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

这里我们可以设计两个位图,刚好占用1G内存,按照如下方式设置

  1. 把A文件读到位图1,把B文件读到位图2
  2. 遍历两个位图,将位图1和位图2进行与&操作,结果存储在位图1中,此时位图1中映射的整数就是两个文件的交集。

image-20230413235946910


3.在100亿个整数中找到出现次数不超过2次的所有整数

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

此题和第一题的思想是一样的,对于出现的次数,可以用两个比特位来表示,一次表示出现次数的状态:

  1. 出现0次(00)
  2. 出现1次(01)
  3. 出现2次(10)
  4. 出现3次及以上(11)

这里同样需要两个位图来解决,只需要对第一题的代码进行改造即可,最后状态是01或10的整数就是出现次数不超过2次的整数。

template<size_t N>
class two_bitset
{
public:
	void set(size_t x)
	{
		int in1 = _bs1.test(x);
		int in2 = _bs2.test(x);
		if (in1 == 0 && in2 == 0)//00
		{
			_bs2.set(x);//01
		}
		else if (in1 == 0 && in2 == 1)//01
		{
			//出现次数置为2
			_bs1.set(x);//10
			_bs2.reset(x);
		}
		else if (in1 == 1 && in2 == 0)//10
		{
			_bs2.set(x);//11
		}
	}
private:
	bitset<N> _bs1;
	bitset<N> _bs2;
};

三、布隆过滤器

1.求两文件交集(近似算法)

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

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

  1. 先读取其中一个文件当中的query,将其全部映射到一个布隆过滤器当中。
  2. 然后读取另一个文件当中的query,依次判断每个query是否在布隆过滤器当中,如果在则是交集(但是会存在误判的风险,不过无法避免,这也是近似算法的特点),不在则一定不是交集。

2.求两文件交集(精确算法)

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

注意:

  • 这里明确指出给出精确算法,我们不能使用布隆过滤器,因为会存在误判,要用上文一开始使用的哈希切分来解决。

我们按照如下的规则来进行哈希切割。

  • 我们假设每个query平均20byte,100亿query就是200G,我们可以把这么个文件分为1000个小文件
  • 依次读取query,通过哈希函数把每个query转换为一个整型,再把这些分别%1000切分到这1000个小文件里头,此时文件A就被分为A0 ~ A999共1000个小文件,文件B就被分为B0 ~ B999共1000个小文件。

image-20230413231529747

由于在切分A文件和B文件的时候,使用的是相同的哈希函数,因此A文件和B文件中相同的query计算的是相同的i值,就被分到了对应的Ai和Bi中,因此我们只需要找到A0与B0的交集、A1与B1的交集……最终把这些集合合并起来就是文件A和文件B的总交集。

image-20230413232215183

而小文件找交集的方法也很简单,如下规则:

  • 我们可以将其中一个小文件加载到内存,并放到一个set容器中,再遍历另一个小文件当中的query,依次判断每个query是否在set容器中,如果在则是交集,不在则不是交集。
  • 如果切分出来的一个小文件过大,需要将此文件再次进行切分,再走一遍这个过程即可。

3.计数法使布隆过滤器支持删除

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

布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。一种支持删除的方法(计数法删除):

  • 将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储空间的代价来增加删除操作。

image-20230413164803445

缺陷:

  1. 无法确认元素是否真正在布隆过滤器中
  2. 存在计数回绕

总结:

  • 布隆过滤器不支持直接删除归根结底在于其主要就是用来节省空间和提高效率的,在计数法删除时需要遍历文件或磁盘中确认待删除元素确实存在,而文件IO和磁盘IO的速度相对内存来说是很慢的,并且为位图中的每个比特位额外设置一个计数器,就需要多用原位图几倍的存储空间,这个代价也是不小的。若支持删除就不那么节省空间了,也就违背了布隆过滤器的本质需求。

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

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

相关文章

气传导和骨传导耳机哪个好?简单科普这两种蓝牙耳机

在生活中&#xff0c;我们经常会用到耳机&#xff0c;特别是在日常娱乐听歌、运动休闲、户外通勤的时候&#xff0c;一款舒适的耳机是必不可少的。 而最近几年&#xff0c;随着科技的发展&#xff0c;各大品牌也相继推出了各种类型的耳机&#xff0c;其中比较热门的就有气传导…

如何在电脑上使用wink一键高清优化短视频画质

如何在电脑上使用wink一键高清优化短视频画质 文章目录 如何在电脑上使用wink一键高清优化短视频画质1.软件简介1.1痛点1.2解决方案 2.实际操作2.1准备工作2.1.1下载雷电模拟器2.1.2下载wink 2.2.安装软件2.2.1安装雷电模拟器2.2.2在雷电模拟器中安装wink 2.3雷电模拟器基本设置…

软件测试实验:Junit单元测试

目录 前言 实验目的 实验内容 实验要求 实验过程 题目一 题目一测试结果 题目二 题目二实验结果 总结 前言 软件测试是软件开发过程中不可缺少的一个环节&#xff0c;它可以保证软件的质量和功能&#xff0c;发现并修复软件的缺陷和错误。软件测试分为多种类型&…

《数据结构》---术语篇

目录 前言: 一.术语 1.1数据 1.2数据结构 1.3逻辑结构和物理结构 二.数据类型和抽象数据类型 ​​​​​​​ ❤博主CSDN&#xff1a;啊苏要学习 ▶专栏分类&#xff1a;数据结构◀ 学习数据结构是一件有趣的事情&#xff0c;希望读者能在我的博文切实感受到&#xff0c…

Numpy从入门到精通——随机生成数组|特定生成数组|规则生成数组

这个专栏名为《Numpy从入门到精通》&#xff0c;顾名思义&#xff0c;是记录自己学习numpy的学习过程&#xff0c;也方便自己之后复盘&#xff01;为深度学习的进一步学习奠定基础&#xff01;希望能给大家带来帮助&#xff0c;爱睡觉的咋祝您生活愉快&#xff01; 这一篇介绍《…

Qt内存管理及泄露后定位到内存泄漏位置的方法

Qt内存管理机制 Qt使用对象父子关系进行内存管理。在创建类的对象时&#xff0c;为对象指定父对象指针。当父对象在某一时刻被销毁释放时&#xff0c;父对象会先遍历其所有的子对象&#xff0c;并逐个将子对象销毁释放。 Qt内存管理代码示例 QLabel *label new QLabel;这里…

【==是判断相等吗?---错辣】C++和JAVA中判断字符串值相等的区别

文章目录 先上结论C中stringJAVA中String回顾结论 参考文章&#xff1a;这里&#xff1b;这里&#xff1b;这里 先上结论 C中的string类型可以使用和!来判断两个字符串的值是否相等&#xff1b;而JAVA不行&#xff0c;JAVA中和!是用来判断两个字符串的地址是否相同&#xff08…

c++学习之类与对象3

目录 成员变量和函数的存储 this指针 this指针的工作原理 this指针的应用 const修饰的成员函数 友元 友元的语法 1.普通全局函数成为类的友元 2.类的某个成员函数作为另一个类的友元 整个类作为另一个类的友元 运算符重载 1 运算符重载的基本概念 2 重载加号运算符…

MySQL数据库学习笔记之存储引擎

存储引擎 MySQL体系结构 连接层 最上层是一些客户端和连接服务&#xff0c;主要完成一些类似于连接处理、授权认证、以及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。 服务层 第二层架构主要完成大多数的核心服务功能&#xff0c;如SQL接口&am…

【JavaScript】6.DOM

文章目录 DOM1. 简介2. 获取元素2.1 根据 ID 获取2.2 根据标签名获取2.3 通过 HTML5 新增的方法获取2.4 特殊元素获取 3. 事件基础3.1 事件概述3.2 事件三要素3.3 执行事件步骤 DOM 1. 简介 文档对象模型&#xff08;Document Object Model&#xff0c;简称 DOM&#xff09;&…

web自动化测试框架落地实施全过程-测试环境搭建 (Selenium+Python)

一、什么是web自动化测试? Web自动化测试是指使用自动化工具模拟用户在Web浏览器中执行的操作&#xff0c;通过编写脚本来自动化执行测试用例&#xff0c;以验证Web应用程序的功能、性能和兼容性等方面的质量。其主要目的是降低测试成本和时间&#xff0c;并提高测试效率和准…

LDAP未授权漏洞验证

因为工作需要&#xff0c;这里验证了下LDAP未授权。 以下是收集到的资料&#xff0c;最后是具体使用&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 更新 2&#xff09;连接ad域有两个地址&#xff1a; ldap://http://XXXXX.com:389 和 ldap://http://XXXXX.…

算法的时间复杂度和空间复杂度(2)

计算斐波那契递归Fib的时间复杂度&#xff1f; long long Fib(size_t N) { if(N < 3) return 1; return Fib(N-1) Fib(N-2); } 因为递归先递推后回归&#xff0c;看起来规律像等比数列&#xff0c;也可以用错位相减法&#xff0c;因为斐波那契数列到第二项就不会再计算了&a…

传输层重点协议之【UDP协议】

1. UDP协议端格式 2. UDP的特点 2.1 无连接 知道对端的IP和端口号就直接传输&#xff0c;不需要建立连接 2.2 不可靠 没有任何的安全机制&#xff0c;发送端发送数据报后&#xff0c;如果因为网络故障数据报无法发送对方&#xff0c;UDP协议层也不会给应用层返回任何错误信…

第六章 Linux实际操作——实用指令

第六章 Linux实际操作——实用指令 6.1 指定运行级别6.2 找回root密码6.3 帮助指令6.3.1 man获得帮助信息6.3.2 help指令6.3.3 搜索引擎帮助更直接 6.4 文件目录类6.4.1 pwd指令6.4.2 ls指令6.4.3 cd指令6.4.4 mkdir 指令6.4.5rmdir指令删除空目录6.4.6 touch 指令6.4.7 cp 指令…

火山引擎边缘云,助力业务敏捷创新

[中国&#xff0c;上海&#xff0c;4 月 18 日]2023 春季火山引擎 FORCE 原动力大会正式举办。大会主论坛&#xff0c;火山引擎总裁谭待围绕云上增长三要素发表了重要演讲。在敏捷迭代专题中&#xff0c;谭待分享了火山引擎边缘云连接与计算无处不在的理念&#xff0c;并于现场…

【fluent udf】定义源项宏时,在迭代计算过程中UDM变量变inf、NAN、发散时如何解决?

一、问题背景 最近做的一个fluent仿真算例里用到源项宏&#xff0c;源项宏里用UDM定义了树脂固化度场。 在迭代计算的过程中&#xff0c;UDM的取值发散成了无穷大inf&#xff08;第一次计算取值是NAN&#xff09;&#xff0c;如下图所示。 由于每一次迭代计算过程中&#xf…

【嵌入式系统与入门】Day01 Arduino开发板

文章目录 1. Arduino概述1.1 是什么&#xff1f;1.2 分类1.3 组成1.4 电源 2. Arduino软件开发流程2.1 明确接口函数2.2 连接板子2.3 打开项目【或者自己编程序】2.4 选择板子类型2.5 选择通讯端口2.6 下载程序2.7. 编写程序代码——程序架构 3. 较常用的封装函数3.1 pinMode(p…

技术报告:Efficient and Effective Text Encoding for Chinese LLaMA AND Alpaca

技术报告&#xff1a;Efficient and Effective Text Encoding for Chinese LLaMA AND Alpaca IntroductionChinese LLaMAChinese AlpacaLora-Fine-tuning实验7Bpre- trainingInstruction-Tuning 13BPre-TrainingInstruct-Tuning Introduction 首先作者说了最近ChatGPT等模型在…

【SpringCloud】2、使用Nacos作为服务注册中心

1、项目搭建 首先&#xff0c;我们需要搭建一个 SpringCloud 微服务项目&#xff0c;后续的文章将基于此项目作为学习演示使用 1、创建 cloud-learn 目录&#xff0c;pom.xml 文件内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> &…