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

BAT面试题——URL查重

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

常规的解决办法

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

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

布隆过滤器

基本思路:

Bloom过滤器

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

算法特点:

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

原因:

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

过程:

对于A中50亿个文件,我们使用一个误报率为1%的bloom过滤器,每个元素需要使用9.6bits,总计需要(50(1089.6)bits=6G(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函数和布隆过滤器的特点:
相同的字符串,处理后结果一定相同
不同的字符串,处理后结果可能相同
返回顶部

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章