通过键 𝑘𝑒𝑦和一个映射函数 𝐻𝑎𝑠ℎ(key)计算出对应的值 𝑣𝑎𝑙𝑢𝑒,把关键码值映射到表中一个位置来访问记录,以加快查找的速度。
哈希表通常解决什么问题:一般哈希表都是用来快速判断一个元素是否出现集合里。
常用数组,set(集合),map(映射)
242.有效字母异位词
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
思路1:
- 先判断字符串 𝑠s 和 𝑡t 的长度,不一样直接返回
False
; - 分别遍历字符串 𝑠s 和 𝑡t。先遍历字符串 𝑠s,用哈希表存储字符串 𝑠s 中字符出现的频次;
- 再遍历字符串 𝑡t,哈希表中减去对应字符的频次,出现频次小于 00 则输出
False
; - 如果没出现频次小于 00,则输出
True.
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
strdict = dict()
for ch in s:
if ch in strdict:
strdict[ch]+=1
else:
strdict[ch]=1
for ch in t:
if ch in strdict:
strdict[ch]-=1
if strdict[ch]<0:
return False
else:
return False
return True
思路2:使用counter哈希表记录每个字母出现的次数。如果两个哈希表相等返回True,否则返回False。
def isAnagram(self, s: str, t: str) -> bool:
##使用counter哈希表记录每个字母出现的次数
from collections import Counter
a_cnt = Counter(s)
b_cnt = Counter(t)
return a_cnt == b_cnt
c++:
bool isAnagram(string s, string t) {
int record[26] = {0};
for (int i = 0; i < s.size(); i++) {
record[s[i] - 'a']++;
}
for (int i = 0; i < t.size(); i++) {
record[t[i] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (record[i] != 0) {
return false;
}
}
return true;
}
349.两个数组的交集
给定两个数组 nums1
和 nums2
,返回它们的交集 。输出结果中的每个元素一定是唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2]
思路1:使用集合
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
##使用集合
return list(set(nums1)&set(nums2))
思路2:
- 先遍历第一个数组,利用哈希表来存放第一个数组的元素,对应字典值设为 11。
- 然后遍历第二个数组,如果哈希表中存在该元素,则将该元素加入到答案数组中,并且将该键值清空。
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
numDict = dict()
nums = []
for num in nums1:
if num not in numDict:
numDict[num] = 1
for num in nums2:
if num in numDict and numDict[num] != 0:
numDict[num] -= 1
nums.append(num)
return nums
202.快乐数
思路:用哈希表来存储为一位生成的数,每次判断该数是否存在于哈希表中。如果已经出现在哈希表里,则说明进入了无限循环,该数就不是快乐数。如果没有出现则将该数加入到哈希表中,进行下一次计算。不断重复这个过程,直到形成闭环或者变为 1。
def getNext(self, n: int):
total_sum = 0
while n > 0:
n, digit = divmod(n, 10)
# divmod() 函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。
total_sum += digit ** 2
return total_sum
def isHappy(self, n: int) -> bool:
num_set = set()
while n != 1 and n not in num_set:
num_set.add(n)
n = self.getNext(n)
return n == 1
1.两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
思路:
哈希表中键值对信息为 $target-nums[i] :i,其中 𝑖i 为下标。
- 遍历数组,对于每一个数 𝑛𝑢𝑚𝑠[𝑖]:
- 先查找字典中是否存在 𝑡𝑎𝑟𝑔𝑒𝑡−𝑛𝑢𝑚𝑠[𝑖],存在则输出 𝑡𝑎𝑟𝑔𝑒𝑡−𝑛𝑢𝑚𝑠[𝑖] 对应的下标和当前数组的下标 𝑖。
- 不存在则在字典中存入 𝑡𝑎𝑟𝑔𝑒𝑡−𝑛𝑢𝑚𝑠[𝑖]的下标 𝑖。
def twoSum(self, nums: List[int], target: int) -> List[int]:
numDict = dict()
for i in range(len(nums)):
if target-nums[i] in numDict:
return numDict[target-nums[i]], i
numDict[nums[i]] = i
return [0]
总结:
- 哈希表也叫散列表,哈希表是一种数据结构,它提供了快速的插入操作和查找操作,无论哈希表总中有多少条数据,在有足够优秀的哈希算法时,插入和查找的时间复杂度都是为O(1)。
- 散列表 ( Hash table ),是根据键(Key)而直接访问在记忆体储存位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表 。表中存储的是一个地址,我们通过键值计算出来的哈希值得到这个地址,再取这个地址中的数据即可。