由一个算法引发的hash讲解

这个春节真长,闲来无事看看算法视频,不得不说老师讲得透彻深刻、通俗易懂,趁热打铁,做个总结

请听题:给N(1<N<10)个自然数,每个数的范围为1~10000,现在让你以最快的速度判断某一个数是否在这N个数内,不能用现有的HashMap,该如何实现?

最直接反应的解决方法

法一:遍历

法二:排序+二分

......

不符合本文标题,也不够高级...

 

更高级的做法:开辟一个数组,最大下标为N个数中最大的数,将N个数作为数组的下标,数组所有值默认0,若该数存在,则将该数下标对应得值改成1,判断一个K在不在N个树中,直接判断a[k]是否为1即可

举个栗子:

给定一组数  2,0,17,31,5,判断10是否在其中。

1、建立数组a[30]

2、将a[0]~a[29]的值都默认成0

3、将a[2]、a[0]、a[17]、a[31]、a[5]改成1

4、判断a[10]是否等于1,若是则在其中,否则不在

这就是最基础的hash算法

 

但是。。。。

有个问题:当最大数据过大时,非常浪费空间。如果题目再加个条件,只给10个空间,怎么办???

取模:10个数,最多就是10个空间。其实就是Hash函数(就是Hash函数,不太懂,

继续以上述栗子为例

2%10=2 => a[2] = 2

0%10=0 => a[0] = 0

17%10=7 => a[7] = 17

31%10=1 => a[1] = 31

5%10=5 => a[5] = 5

 

但是。。。。

又有个问题:当有两个或以上的数取模后值一样怎么办??这就叫hash碰撞,也就是hash冲突

使用hash算法时,有很多办法解决hash冲突

法一:使用链表,jdk1.7的HashMap就是用的该算法

举个栗子:10,2,32,44,77

a[2]=2,32

缺点:当所有数取模后的值都一样的时候,就变成了一个单链表,查找很麻烦

注:Hash的效率取决于冲突的数量,冲突越多,效率就越低,所以一个好的Hash函数可以解决Hash的效率

法二:使用链表+红黑树,当链表节点大于8时,用红黑树,经过测试后总结。jdk1.8 HashMap用的该算法

 

 

posted @ 2020-02-06 17:11  Lynne~  阅读(200)  评论(4编辑  收藏  举报