哈希表基础知识
https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
需要快速判断一个元素是否出现在集合里的时候就要考虑使用哈希法
哈希表牺牲了空间换取时间,因为要使用额外数组、set或map来存放数据,才能实现快速查找
- 根据关键码的值而直接进行访问的数据结构
- 数组就是一张哈希表
- 数组的下标 = 哈希表的关键码
哈希函数
通过hashcode把名字转化为数值:hashfunction = hashcode(name) % table size 【一行hashcode(name)数值大于hash table大小,对tablesize取模 % table size 】
index = hashfunction(name)
哈希碰撞
hashcode将两个数据映射到同一个索引上,例如出现于当名字个数大于hash table size
解决方法:
- 拉链法:发生冲突的元素被存在链表中,可以通过hash table的索引找到
- 线性探测法:必要条件事table size > data size,通过hash tabel中的空位解决碰撞问题
常见哈希结构
- 数组
- 集合(set)
- 映射(map)
242.有效的字母异位词
初步想法
时间紧张,并没有做过哈希表的题,直接进入题解
题解
https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html
a-z对应0-25
定义数组hash长度26,遍历第一个数组记录每个字母出现的频率,再遍历第二个字符串
hash = [0]*26 # 初始化为0
for i in range(0,len(s)):
hash[s[i]-'a'] += 1 # 编译器会自动用字母的ASCII做计算
for j in range(0,len(t)):
has[t[i] - 'a'] -= 1
for i in range(0,26):
if hash[i] != 0:
return False
return True
代码:
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
hash = [0]*26 # 初始化为0
for i in range(0,len(s)):
hash[ord(s[i])-ord('a')] += 1 # 编译器会自动用字母的ASCII做计算
for j in range(0,len(t)):
hash[ord(t[j]) - ord('a')] -= 1
for i in range(0,26):
if hash[i] != 0:
return False
return True
总结
- 数据量小用数组
- 数据量大用set
- 有key-value pair 用map
349. 两个数组的交集
初步想法
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return list(set(nums1) & set(nums2))
题解
https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html
- set: 将num1转成哈希表,遍历num2中的值是否在哈希表中出现过
- 数组:
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
count1 = [0]*1001
count2 = [0]*1001
result = []
for i in range(len(nums1)):
count1[nums1[i]]+=1
for j in range(len(nums2)):
count2[nums2[j]]+=1
for k in range(1001):
if count1[k]*count2[k]>0:
result.append(k)
return result
202. 快乐数
初步想法
题不难,新建一个set记录每次算完平方和都是什么数,当数字重复出现的时候说明进入循环,也就不可能是快乐数,这是return False的唯一情况
每一次先检查平方和是否等于一,等于返回True,不能与判断是否要返回False,不反悔则将新的放平和加入已有的平方和的set里
class Solution:
def isHappy(self, n: int) -> bool:
total = set()
total.add(n)
while 1:
num = [int(i) for i in str(n)]
n = sum([i**2 for i in num])
if n == 1:
return True
elif n in total:
return False
else:
total.add(n)
题解
https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html
跟自己的思路是一样滴
1. 两数之和
初步想法
这题的index 和value可以是map-value pair,所以想用map解决
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
index = 0
hash = {}
for i in range(len(nums)):
hash[nums[i]] = i
print(hash)
while index <= len(nums):
current = nums[index]
need = target - current
try:
if index != hash[need]:
return index, hash[need]
else:
index += 1
except:
index += 1
题解
https://programmercarl.com/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.html
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
records = dict()
for index, value in enumerate(nums):
if target - value in records: # 遍历当前元素,并在map中寻找是否有匹配的key
return [records[target- value], index]
records[value] = index # 如果没找到匹配对,就把访问过的元素和下标加入到map中
return []