欢迎关注,敬请点赞!
问题描述:
给你A、B两个文件,各存放50亿条URL,每条URL占用64字节,内存限制是16G,让你找出A、B文件共同的URL。
常规的解决办法
也是最容易想到的,就是对于文件A,读入内存。对于文件B中的每一个元素,判断是否在A中出现过。
我们来分析一下这样做的空间和时间复杂度:第一步,读入文件到内存,需要的内存是
,显然我们在实际中没有那么大的内存。
另外,通过遍历A文件和B文件中的每一个元素,需要的时间复杂度是 ,M、N是两个文件元素的大小,时间复杂度是 。
布隆过滤器
基本思路:
- 设数据集合 ,含n个元素,作为待操作的集合。
- Bloom Filter用一个长度为m的位向量V(Bit Array),表示集合中的元素,位向量初始值全为0。
- k个具有均匀分布特性的散列函数 。
- 对于要加入的元素,首先经过k个散列函数产生k个随机数 ,使向量V的相应位置( )均置为1。集合中其他元素也通过类似的操作,将向量V的若干位置为1。
- 对于新要加入的元素进行检查,首先将该元素经过上步中类似操作,获得k个随机数 ,然后查看向量V的相应位置 上的值,若全为1,则该元素已经在之前的集合中,为旧元素;若至少有一个0存在,表明此元素不在之前的集合中,为新元素。
算法特点:
返回顶部
对于已经在集合中的元素,通过5中的查找方法,一定可以判定该元素在集合中;
对于不在集合中的元素,可能会被误判在集合中。
原因分析:
hash函数的特点是,对于相同的字符串,经过hash函数处理后,结果必然相同;
而不同的字符串,经过hash函数处理后,结果可能相同(概率很小)。
过程:
对于A中50亿个文件,我们使用一个误报率为1%的bloom过滤器,每个元素需要使用9.6bits,总计需要 ,在内存的使用上,是符合我们要求的,然后对于使用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 查看本文章