一、概念
哈希表(Hash Table),数据结构,用于存储和检索键值对(Key-Value pairs)。
包含:
键 | key | 键通过哈希函数转换成“值”的索引 |
哈希函数 | Hash(key) | 中介 |
值 | value | 与键配对 |
哈希表的核心思想是使用哈希函数将键转换为索引,然后将值存储在对应索引位置的存储桶中。
通常基于数组实现的,通过数组的下标来访问存储桶。
二、优点:
高效存储(插入)和查找、空间效率高、可用表来存储计算好的结果(缓存)、当字典、数据库检索
三、哈希函数:
“魔术师”,特殊的魔法规则:
将任意大小的输入(比如一段文本、一个数字或者一个对象)转化成一个固定长度的输出,称为哈希值。
哈希函数输出范围固定。
哈希函数特性:
一致性:同输入同输出。
唯一性:不同输入应该不同输出。
高效性:快。
四、常见的哈希函数方法:
1.直接地址法(Direct Addressing):适用键的范围较小且已知,索引位置即为键的值。要求:键的范围较小,否则会导致内存浪费。
2.除留余数法(Division Method):键除以一个固定的数(通常是哈希表的大小),取余数作为哈希值。例如,如果哈希表的大小是10,键为21,则哈希值为21除以10的余数1。
3.乘法哈希法(Multiplication Method):将键乘以一个介于0和1之间的常数,然后取乘积的小数部分乘以哈希表的大小,最后取整数部分作为哈希值。好处:更好地分散键的分布,减少哈希冲突的可能性。
4.布尔哈希法(Boolean Hashing):适用于位向量的哈希函数方法。对于给定的键,布尔哈希函数将键的每个位进行逻辑运算,例如按位异或或按位与,然后将结果作为哈希值。
5.加法哈希法(Additive Hashing):适用于字符串类型的键。它将字符串中每个字符的 ASCII 值相加,然后取总和的余数作为哈希值。简单应用:行;较长的字符串:可能不太行,有较高的哈希冲突。
五、问题:
哈希冲突(Hash Collision):
不同的键经过哈希函数计算后得到相同的哈希值,GG了。
解决方法:
1.链表法(Chaining):
基于以下思想:在哈希表的每个位置上,我们不仅存储一个键值对,也存储一个链表(或其他数据结构),用于存储具有相同哈希值的键值对。
当发生哈希冲突时,将它们添加到同一个位置上的链表中(见图1,好理解),这个位置上的链表对应相同哈希值的键值对集合。
查找时,先通过哈希函数找到相应的位置,然后遍历该位置上的链表,直到找到目标键值对或遍历完整个链表。
图1 链表法示意图
2.开放地址法(Open Addressing):
在哈希表的每个位置上,存储一个键值对。当发生哈希冲突时,可以通过探测(Probing)方法,在哈希表中寻找下一个可用的位置来存储。常见的探测方法包括线性探测(i+1)、二次探测(i+2^1或2或3)和双重哈希等。当插入或查找时,如果发现目标位置已经被占用,则继续探测下一个位置,直到找到空闲位置或者遍历完整个哈希表。
六、python代码:
哈希表在python==字典
#字典创建方式 keys = ["key1", "key2", "key1"] values = ["value1", "value2", "value3"] dictionary = dict(zip(keys, values)) print(dictionary) |
七、leedcode解题:
217. 存在重复元素
idea:利用python字典的键不能相同的特点:相同,后一个值会覆盖前一个,导致字典长度与原列表长度不一致。
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
values=[ _ for _ in range(len(nums))]
dic=dict(zip(nums,values))
if len(dic) != len(nums):
return True
else:
return False