海量数据处理十题

题目

1)给⼀一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
2)与上题条件相同,如何找到top K的IP?如何直接用Linux系统命令实现?
3)给定100亿个整数,设计算法找到只出现一次的整数?
4)给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
5)1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数?
6)给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法
7)如何扩展BloomFilter使得它支持删除元素的操作?
8)如何扩展BloomFilter使得它支持计数操作?
9)给上千个⽂文件,每个文件大小为1K~100M。给n个词,设计算法对每个词找到所有包含它的文件,你只有100K内存
10)有一个词典,包含N个英文单词,现在任意给一个字符串,设计算法找出包含这个字符串的所有英文单词

思考方向(很重要)

关于海量数据的题目,有两个基本方向:

  1. 首先看是否可以通过特殊的数据结构解决,比如位图,堆,哈希等,无法解决,思考另一个方向
  2. 能否通过切割数据,再通过方向1来进行解决,因为对于海量数据来说,往往直接解决有困难的地方都是数据过多空间不够问题,我们可以思考是否能够通过切割结合数据结构来解决

切割数据其实就是分治思想,分治即当一个问题无法一次结局的时候,切分成子问题进行解决。
二叉树的递归遍历就是一种典型的分治;快速排序的快速切割数组也是分治;斐波那契数列的递归求解也是分治;生活中当我们遇到困难的时候,可以将其分解成很多小问题进行依次解决;写代码无从下手的时候,可以切割成若干个功能函数一个一个写,这也是分治。
分治很常见,可以说无处不在。

解题思路

1)查找出现次数最多的IP地址

给⼀一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?

分治 + 哈希

  1. 将数据分割成若干的小份,但不是均分,可以按照某一个哈希函数来切割,将映射值为同一个数的IP分到一个文件去,这样相同的IP会出现在同一个文件内。分的文件个数不能太少,因为难免会出现某一个文件出现的地址多的情况,(我们并不是均分,当均分为100份的话,平均下来也是一个文件1G,如果出现该情况,可能会出现一个log file有2个G甚至更多,有可能存不下),为了避免这种情况,分的份数合适,即使出现几个文件较大,也不会太大。
  2. 对每个文件依次处理,每个文件用哈希表进行映射,哈希表要构造成key-value模型,也就是映射的位置不止存IP地址(key),还要跟一个出现的次数(value),找出出现次数最多的IP并保存。
  3. 将每个文件中出现次数最多的IP地址,放在一起再选出出现次数最多的IP,此问题解决。

本题的关键在于:使用同一个哈希函数分割IP时,相同的IP只会映射到同一个文件。

2)查找出现次数在前K的IP地址

与上题条件相同,如何找到top K的IP?如何直接用Linux系统命令实现?

分治 + 哈希

  1. 同上题一个思路,将文件分割成若干小份。
  2. 同上题思路一样,用key-value哈希表进行映射,不同的地方在于接下来的处理,针对每个文件的哈希表,将其中的value当做要比较的值,运用Top K解决方法,也就是堆来得到该文件内前K个出现次数最多的IP
  3. 将所有文件的出现次数前K个IP地址放在一起,再找出前K个IP地址,就是所要求的IP,至此问题解决。

关于堆实现Top K:有一堆海量数据,需要求最大的K个数,排序太耗时间,这个时候用的即堆,建一个元素个数为K个的堆,由于要找最大的N个数,所以要建小堆(没错就是小堆),然后依次从文件读取数据,当读入数据大于堆顶元素,就取代堆顶元素,然后重新调整为小堆,直至元素读取完成。

Linux命令:不会,还没学,学了补上

3)找只出现一次的整数

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

位图扩展

整数再多,也无非42亿9000万个,在这里哈希显然是不行的,耗费的空间太多,此时,位图的优势就体现出来了,节省空间,所以此题可以用特殊的数据结构,也就是位图解决。

看图简单了解位图
位图原理示意图

关于位图:点击此处了解更多关于位图的信息
我们可以算一笔账:

42亿9000万个位 ≈ 5亿个字节
1byte = 8bit
1KB = 1024byte
1MB = 1024KB
1GB = 1024MB
10的9次字节约为1G,5亿个字节约为0.5G = 512mb

也就是说用位图实现这个题完全可以,再合适不过了,但是一个位不足以解决问题,如果一个数没出现为0,出现一次可以置1,出现两次就无法表示,置1和置0都不合适,所以此题用两位来存一个数的信息。
从头到尾遍历一边数,将其信息存入位图,没出现为00,出现一次为01,出现两次为10,出现三次为11,最后只需要打印信息为01的数即可。

4)找存整数文件交集

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

思路一:

位图 + 比对

  1. 用位图存储整数,这个题不需要统计出现的次数,因此只需要一个位即可,需要内存是512MB,只需要把第一个文件内的数存入位图即可。
  2. 第二个文件依次读取,同位图比较,位图中有信息说明该处为交集,直至读取结束。
思路2:

分治 + 比对

  1. 整数无非是32位,将其按位切割,对文件1进行切割,第一位(也就是最高位)为1的切割进一个文件,第一位(最高位)为0进入另一个文件;
  2. 重复第1步,对切割的文件进行再次切割,第1次是第1位,第2次对第2位进行切割,直至切割完毕;
  3. 文件2每个数进行查找,由于已经进行切割,查找类似于二分查找,效率很高,最坏也不过查找32次。

5)找出现次数为2次的整数

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

思想:位图扩展

思路同第三题,只需要打印序列为10的数即可,不做过多赘述。

6)找Query文件交集

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

精确算法

分治 + 哈希 + 比对

  1. 将两个文件用同一个哈希函数进行切割,同样的query会进入编号相同的文件
  2. 同样编号的文件取文件1切割出来的n号文件,对每条query进行映射,然后用文件2切割出来的n号文件进行逐条查找,看是否存在,求出交集。
  3. 重复直至所有编号相同的文件比对完毕。
    文件切割示意图
近似算法

布隆过滤器 + 比对

  1. 将query通过三个哈希函数进行映射,用布隆过滤器存储文件1每条query的信息,由于布隆过滤器是用多个位判断一条信息是否存在,而且该位还可能代表另一条query存在,所以存在误判。
  2. 文件2的query依次通过哈希函数来查找布隆过滤器中对应的位,看query是否存在,这就是近似算法。

简单了解布隆过滤器
布隆过滤器示意图

使用布隆过滤
关于布隆过滤器:点此了解布隆过滤器

7)布隆过滤器支持删除操作

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

布隆过滤器位存储扩展为整型存储

布隆过滤器由于一个位的状态可能和多条信息关联,删除不能简单的置为0,所以这个时候就需要对当前位置的记录信息条数进行计数,将布隆过滤器扩展成一个int记录信息
每有一条信息进入,找到映射的三个位置,就+ 1,而不是简单的置1置0
删除操作只需要找到映射的三个位置- 1即可

8)布隆过滤器支持计数

如何扩展BloomFilter使得它支持计数操作?

布隆过滤器位存储扩展为整型存储

同第七题

9)给词查文件

给上千个⽂文件,每个文件大小为1K~100M。给n个词,设计算法对每个词找到所有包含它的文件,你只有100K内存

倒排索引

  1. 将n个单词构成一颗二叉搜索树,如果是中文,则先经过分词再构建;
  2. 对每个文件的每个词进行搜索,如果该词存在,将其文件名挂在对应单词后面,直至文件读取结束;
  3. 每个节点后所挂的文件信息列表即需要获取的信息

看图了解倒排索引
倒排索引

10)字符串查找

有一个词典,包含N个英文单词,现在任意给一个字符串,设计算法找出包含这个字符串的所有英文单词

字典树

字典树是一种特殊的树,根节点为空,每个节点只有一个字母,如图:
字典树

关于字典树的原理仅限于了解,目前还是太菜,等学习了之后我会补上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值