提示:咱们这几篇文章重点讲哈希函数,这些个知识点,用来跟互联网大厂的面试官聊的,不用写代码!
重要的关于哈希函数定义和应用的基础知识:
【1】哈希函数1:用于资源限制类机器统计文件或词频
【2】哈希函数2:用于哈希表的存储和扩容
Hash函数译为哈希函数,又称散列函数。
是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出的值称为散列值或消息摘要。
简单来说就是一种将任意长度的输入消息压缩成某一固定长度的消息摘要的函数。
它具备以下的性质(哈希函数所必须的性质):
(1)f的输入无限:可应用于任意大小的数据块。
(2)f的输出有限:产生定长的输出。
(3)f没有随机性,同样的输入一定是同样的输出
(4)多对一:f对不同的输入,可能是同样的输入,因为(1)(2)导致输入很多,但是输出固定那么些
(5)f有均匀性或分散性:输入不同,但是输出是离散均匀分布在输出域中的;
情况是这样的:比如你在爬虫
要收集好多网站的url,但是你收集的连接可能重复呢?
那重复就没意思了
所以呢?
设计一个过滤器:布隆过滤器,将爬虫爬过的连接x,统统记录在黑名单中,然后你找一个新的连接y,看看在和名单中么?
在,不要爬了
不在?爬
暴力搜索:互联网有成见上万的连接,你N越来越大,你去对比一个字符串在一大篇文章(黑名单)中,是否出现过?
这事可以干,用AC自动机查呗,但是这复杂度可就高了…………
咱们这么搞:用一个位图数组来标记,int数字由32位二进制数表示,每一个01,表状态
来一个连接,在低位标记1
不妨设你要存100*32个连接,那你要准备100长度的数组flag,每个数字int类型,32位长状态位
那t=453这个数字来了,你怎么标记?
先分隔,你在哪行?再决定在哪列?
row=453/32,每一个行,不是32列吗,这样你的行数就知道了
那你是32位中的哪个位)(列)呢?
直接column=453%32即可–对应0–31中的某个位置
比如row=2行,column=3位
那直接下面标记1即可,代表啥呢?543这个数字来过了
如果你嫌100这种长度不够你的数据放,那你可以用long类型的数组flag,这样的话,64位状态呢,非常长
这样就是10064这么多数字可以放
如果你还是嫌不够,可以用矩阵来存
arr=100100再×32或者64啥的
来了一个数字t
怎么定行?列?位?
行row=t/32×100或64×100【因为每一片都是32×100这么多位置】
列column=t-row32×100 / 32或64【剩下的举例,再按照一维的操作】
位=t-row32×100 %32或64
这种有点浪费了其实
咱们这么搞,别让1个1代表一个数字
我们这么搞
选取T个哈希函数f1–fT
来一个数字t=453
咱们这么做:让t经过所有哈希函数f1–fT,再模M
得到不同的输出k1–kT
将N位数组的不同k位置标记为1
这就大大节约了空间哇,多个状态位同时为1,证明453来过了
下次来一个数字,如果仍然得到了k1–kT都是同一个1,咋说明它来过了
所以咱们的哈希函数要尽量分开,别碰撞!
那么自然设计布隆过滤器,就需要问M多大呢?你要放多大的位呢?32,64?等等
面试的时候,你别傻乎乎就讲如何设计,先问面试官,你的数据量多少?咱们要用多少位来设计布隆过滤器?
然后才开始设计,原理就是上面的原理了。
设计流程:
布隆过滤器的算法总结:
(1)初始化时,需要一个长度为n比特的数组,每个比特位初始化为0;
(2)然后需要准备k个hash函数,每个函数可以把key散列成为1个整数;
(3)个key加入集合时,用k个hash函数计算出k个散列值,并把bit数组中对应的比特位置为1;
(4)判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果有比特位是0,则该key一定不在集合中。
布隆在海量数据查询中以优异的空间效率和低误判率有非常广泛的应用,其中包括但不限于:
(1)检查单词拼写正确性 --类似于AC自动机干的事情了,grammarly估计用了这玩意
(2)检测海量名单嫌疑人
(3)垃圾邮件过滤
(4)搜索爬虫URL去重
(5)redis缓存穿透过滤
本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。
提示:重要经验:
1)布隆过滤器本质是填位图标记出现过的连接
2)用很多哈希函数,可以让多个位同时为1标记这个数据出现过,参数M位状态要知道。
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。