第一次近距离接触哈希,一点点啃这个知识点。
705 设计哈希集合,采用链表的结构
参考链接
class MyHashSet:
def __init__(self):
self.keyRange=769 #预定义769个桶
self.bucketArray=[Bucket() for i in range(self.keyRange)]
def _hash(self,key):
return key%self.keyRange #哈希函数使用模运算取余数。理论上桶越多越不容易发送碰撞,空间和碰撞之间的权衡
def add(self,key):
bucketIndex=self._hash(key)
self.bucketArray[bucketIndex].insert(key)
def remove(self,key):
bucketIndex=self._hash(key)
self.bucketArray[bucketIndex].delete(key)
def contains(self,key):
bucketIndex=self._hash(key)
return self.bucketArray[bucketIndex].exists(key)
class Node:
def __init__(self,value,nextNode=None):
self.value=value
self.next=nextNode
class Bucket:
def __init__(self):
self.head=Node(0)
def insert(self,newValue):
if not self.exists(newValue):
newNode=Node(newValue,self.head.next)
self.head.next=newNode
def delete(self,value):
prev=self.head
curr=self.head.next
while curr:
if curr.value==value:
prev.next=curr.next
return
prev=curr
curr=curr.next
def exists(self,value):
curr=self.head.next
while curr:
if curr.value==value:
return True
curr=curr.next
return False
时间复杂度O(N/K),N是指所有可能值数量,K指的是预定义的桶数,也就是质数769。假设值是平均分布的,那么一个桶的大小是N/K,最差情况遍历整个桶,时间复杂度O(N/K)
空间复杂度O(K+M)K是预定义的桶数,M指的是N中已插入到哈希集合HashSet中值的数量
706设计哈希映射
上面哈希集合是值,这里的哈希映射是键值对(key,value)
对应Python中的dict,Java中的Hashmap,哈希表的特性是可以根据给出的key快速访问value
设计哈希表从两点进行考虑,如何设计哈希方法和如何避免哈希碰撞
最简单的哈希方法是取模运算,同时为了降低哈希碰撞的概率,通常取素数的模,例如素数2069
class MyHashMap:
def __init__(self):
self.keyRange=2069
self.hash_table=[Bucket() for i in range(self.keyRange)]
def put(self,key,value):
BucketIndex=key%self.keyRange
self.hash_table[BucketIndex].update(key,value)
def get(self,key):
BucketIndex=key%self.keyRange
return self.hash_table[BucketIndex].search(key)
def remove(self,key):
BucketIndex=key%self.keyRange
self.hash_table[BucketIndex].delete(key)
class Bucket:
def __init__(self):
self.bucket=[]
def search(self,key):
for (k,v) in self.bucket:
if k ==key:
return v
return -1
def update(self,key,value):
found=False
for i,kv in enumerate(self.bucket):
if key==kv[0]:
self.bucket[i]=(key,value)
found=True
break
if not found:
self.bucket.append((key,value))
def delete(self,key):
for i,kv in enumerate(self.bucket):
if key==kv[0]:
del self.bucket[i]
时间复杂度O(N/K),N是指所有可能值数量,K指的是预定义的桶数,也就是质数769。假设值是平均分布的,那么一个桶的大小是N/K,最差情况遍历整个桶,时间复杂度O(N/K)
空间复杂度O(K+M)K是预定义的桶数,M指的是N中已插入到哈希集合HashSet中值的数量