关于我的 Leetcode 题目解答,代码前往 Github:https://github.com/chenxiangcyr/leetcode-answers
使用场景:数据字典,数据判重,集合求叫。
基本思想:
- 定义一个位数组,长度为 m
- 定义 k 个独立的哈希函数
- 输入元素个数为 n
插入元素:对于输入的某一个元素,分别计算 k 个哈希函数对应的哈希值,将位数组上对应的位置设为 1。
查找元素:如果发现所有 k 个哈希函数对应的位置都是 1,则说明存在。
优点:
- 插入和查找为常数时间
- k 个独立的哈希函数可以并行计算
- 两个 Bloom Filter 的交并差运算可以使用位操作实现
缺点:
- 不支持删除一个已经插入的元素
- 改进:Counting Bloom Filter(CBF),将原来位数组中的每一位由 bit 扩展为 n-bit 计数器
注意:不能保证查找的结果 100% 是正确的,即存在 false positive 假阳率,显示某个元素存在,实际该元素不存在。
对于给定的 m 和 n,哈希函数的个数 k 由如下公式确定:
k = (m / n) * ln^2 ≈ (m / n) * 0.7
,此时假阳率约为 2^-k ≈ 0.6185^(m/n)
对于给定的 假阳率 p 和 n,位数组长度 m 由如下公式确定:
m = -(n*ln^p) / (ln^2)^2
,若 p = 1%
,则 m ≈ 13 * n
问题1:两个文件,各存放 50 亿条 URL,每条 URL 占用 64 字节,内存容量为 4G,找出文件中共同的URL。
分析:
利用第一个文件构造 Bloom Filter,内存为 4G,则位数组长度 m 为:
m = 4G byte = 40亿 byte = 320 亿 bit
若假阳率 p = 1%
,则最优 m ≈ 13 * n = 13 * 50亿 = 650 亿
,跟 320 亿相差不多。
此时,哈希函数个数 k = (m / n) * 0.7 = (320 亿 / 50 亿) * 0.7 ≈ 5
对第二个文件中的每一个 URL,依次进入 Bloom Filter 检测。