BAT面试题——URL查重及布隆过滤器Bloom

欢迎关注,敬请点赞!

问题描述:
给你A、B两个文件,各存放50亿条URL,每条URL占用64字节,内存限制是16G,让你找出A、B文件共同的URL。

常规的解决办法

也是最容易想到的,就是对于文件A,读入内存。对于文件B中的每一个元素,判断是否在A中出现过。
我们来分析一下这样做的空间和时间复杂度:第一步,读入文件到内存,需要的内存是 50 ( 10 8 ) 64 = 320 G 50*(10**8)*64 = 320G ,显然我们在实际中没有那么大的内存。

另外,通过遍历A文件和B文件中的每一个元素,需要的时间复杂度是 o ( M N ) o(M*N) ,M、N是两个文件元素的大小,时间复杂度是 ( 50 亿 50 亿 ) (50亿*50亿)

布隆过滤器

基本思路:

Bloom过滤器

  1. 设数据集合 A = { a 1 , a 2 , , a n } A = \lbrace a_1, a_2, ……, a_n \rbrace ,含n个元素,作为待操作的集合。
  2. Bloom Filter用一个长度为m的位向量V(Bit Array),表示集合中的元素,位向量初始值全为0。
  3. k个具有均匀分布特性的散列函数 h 1 h 2 h k h_1,h_2,……,h_k
  4. 对于要加入的元素,首先经过k个散列函数产生k个随机数 r 1 r 2 r k r_1,r_2,……,r_k ,使向量V的相应位置( b 1 b 2 b k b_1,b_2,……,b_k )均置为1。集合中其他元素也通过类似的操作,将向量V的若干位置为1。
  5. 对于新要加入的元素进行检查,首先将该元素经过上步中类似操作,获得k个随机数 r 1 r 2 r k r_1,r_2,……,r_k ,然后查看向量V的相应位置 b 1 b 2 b k b_1,b_2,……,b_k 上的值,若全为1,则该元素已经在之前的集合中,为旧元素;若至少有一个0存在,表明此元素不在之前的集合中,为新元素。

算法特点:

返回顶部
对于已经在集合中的元素,通过5中的查找方法,一定可以判定该元素在集合中;
对于不在集合中的元素,可能会被误判在集合中。

原因分析:

hash函数的特点是,对于相同的字符串,经过hash函数处理后,结果必然相同;
而不同的字符串,经过hash函数处理后,结果可能相同(概率很小)。

过程:

对于A中50亿个文件,我们使用一个误报率为1%的bloom过滤器,每个元素需要使用9.6bits,总计需要 ( 50 ( 10 8 9.6 ) b i t s = 6 G (50*(10**8)*9.6)bits = 6G ,在内存的使用上,是符合我们要求的,然后对于使用A文件建立的bloom过滤器,我们遍历B中的每一个元素,判断是否在A中出现过。

from pybloom_live import BloomFilter  # 也可以from pybloom import BloomFilter
# 生成一个容量为50亿个元素,错误率为1%的bloom过滤器
bloom_A_file =  BloomFilter(capacity = 5000000000, error_rate=0.01)
# 至少保持电脑的可用内存在8G以上


with open(file_A) as f1:              # 遍历A文件中的每一个元素,加入到bloom过滤器中
    for sel in f1:
        bloom_A_file.add(sel)
        
with open(file_B) as f2:              # 遍历B文件,找出在A文件中出现的元素,并打印出来
    for sel in f2:
        if sel in bloom_A_file:
            print(sel)

总结

hash函数和布隆过滤器的特点:
相同的字符串,处理后结果一定相同
不同的字符串,处理后结果可能相同

欢迎关注,敬请点赞!
返回顶部

扫描二维码关注公众号,回复: 11157702 查看本文章
原创文章 43 获赞 14 访问量 2851

猜你喜欢

转载自blog.csdn.net/weixin_45221012/article/details/105408768