哈希表理论基础
哈希表的概念
(hash table)是根据关键码的值而直接进行访问的数据结构。简单来讲,数组就是一张哈希表,哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。
- 一般哈希表都是用来快速判断一个元素是否出现集合里
哈希函数
哈希函数是一种将数据映射到固定大小值的函数。它接受输入数据并通过一系列计算将其转换为固定长度的哈希值或哈希码。哈希函数的输出通常是一个数字或一段固定长度的二进制字符串。
哈希碰撞
当两个及以上的数据都映射到了同一个索引下标的位置,就出现了哈希碰撞。
一般情况下哈希碰撞的解决方法有两种,拉链法和线性探测法。
拉链法就是选择适当的哈希表大小,这样既不会大量浪费内存,也不会因为链表太长而在查找上浪费太多时间。
242.有效的字母异位词
第一种思路的两个代码实现如下,这种思路本质上就是先把一个字符串放到一个列表中去,然后遍历字符串t中的字符,若字符存在在列表中,则删除。若不存在直接报错。最后如果把第一个字符串里的东西全删光了,就说明确实是有效的字母异位词。
非常蠢的思路,内存用了超级多。
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
hashA = []
hashB = []
for i in s:
hashA.append(i)
for j in t:
if j in hashA:
hashA.remove(j)
else:
hashB.append(j)
return hashA == [] and not hashB
也是用了数组,但是内存占的很多。
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
n = list(t)
for i in s:
if i in n:
n.remove(i)
else:
return False
return not n
看了代码随想录的方法,确实我也想到了做一个26位哈希表,但以为这样会麻烦。显然我想错了
用相对值计算真的很聪明!!!
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
# 定义一个大小为26的数组。初始化为0
# 这个数组record用来记录字符串s里字符出现的次数
record = [0]*26
for i in range(len(s)):
record[ord(s[i])-ord("a")]+=1
print(record)
for i in range(len(t)):
record[ord(t[i])-ord("a")]-=1
for i in range(26):
# record数组如果有的元素不为0,则说明字符串s和t肯定不是字母异位词
if record[i]!=0:
return False
#如果有一个元素不为零,则可以判断字符串s和t不是字母异位词
break
return True
349. 两个数组的交集
利用集合的性质
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
a = set()
for num1 in nums1:
if num1 in nums2:
a.add(num1)
return list(a)
直接用set()
函数中的方法
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return list(set(nums1) & set(nums2))
202. 快乐数
总体思路:将每次生成的数字都检查是否在哈希表中,如果哈希表中已经有了这个数字,那么这个数字就不是快乐数。如果没有这个数字就将其放入哈希表。当数字为1时,这个原数字就是快乐数。(需定义一个实现当前数 数位分离求各位平方和的函数。
class Solution:
def isHappy(self, n: int) -> bool:
# 将当前数进行数位分离,求各位上平方的和
# 每次生成的数,查是否在哈希集合中,在的话就不是快乐数,不在的话就添加到集合里。
# 使用集合记录过程数据
record = set()
while True:
# 将当前这个数字替换为它每个位置上的数字的平方和
n = self.getNext(n)
if n ==1:
return True
if n in record:
return False
else:
record.add(n)
# 求正整数num每个位置的平方和
def getNext(self,num):
happy_sum = 0
while num:
# 先取余得到num的低位数字 算出平方
happy_sum += (num%10)**2
# 再对10整除得到高一位的数字
num = num//10
return happy_sum
1. 两数之和
最蠢的暴力解法
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
for j in range(1,len(nums)):
if nums[i]+nums[j] == target and i != j:
return [i,j]
想到了target-nums[i]
的思路
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
value=target-nums[i]
if value in nums and i!=nums.index(value):
return [i,nums.index(value)]
第2种方法的升级版,内存减少了一些,使用了 python中的内置函数
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 利用哈希表的映射关系实现缩短寻找target-x
hashlist = dict()
# 用enumerate函数遍历数组的下标和值
for i, num in enumerate(nums):
if target-num in hashlist:
return [i,hashlist[target-num]]
# 数组的值作为键 下标作为值
hashlist[nums[i]]=i
return []