哈希表理论基础:
-
当需要快速判断一个元素是否出现在集合里的时候,则优先考虑哈希表。
-
出现哈希碰撞:
-
拉链法:将发生碰撞的两个或多个元素存储在链表中
- tip:拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。
- 线性探测法:依靠哈希表中的空位来解决碰撞问题,出现碰撞则向下继续寻找可用空位。
- tip:使用线性探测法,一定要保证tableSize大于dataSize
-
-
常见哈希结构:list, set, dict (in python)
242.有效的字母异位词
-
题解1:
class Solution(object):
def isAnagram(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
temp = {}
for char in s:
if char not in temp:
temp[char] = 1
else:
temp[char] += 1
for char in t:
if char in temp:
temp[char] -= 1
else:
temp[char] = 1
return True if all(value == 0 for value in temp.values()) else False
-
题解2: (followup question)
- The function ord() returns an integer representing the Unicode character.
- for example, ord('a') = 97, ord('z') = 122, totally 26 characters or letters (a-z).
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
temp = [0] * 26
for char in s:
temp[ord(char) - ord('a')] += 1
for char in t:
temp[ord(char) - ord('a')] -= 1
return all(x == 0 for x in temp)
383. 赎金信
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
temp = [0]*26
for char in ransomNote:
temp[ord(char) - ord('a')] += 1
for char in magazine:
temp[ord(char) - ord('a')] -= 1
return all(x <= 0 for x in temp)
49. 字母异位词分组
Q: 如果只是判断 if temp not in res:,则会报错
A:How to Handle Unhashable Type List Exceptions in Python | Rollbar
- The Python
TypeError: unhashable type: 'list'
usually means that a list is being used as a hash argument. This error occurs when trying to hash a list, which is an unhashable object. For example, using a list as a key in a Python dictionary will cause this error since dictionaries only accept hashable data types as a key. The standard way to solve this issue is to cast a list to a tuple, which is a hashable data type.
# python 2
class Solution(object):
def groupAnagrams(self, strs):
"""
:type strs: List[str]
:rtype: List[List[str]]
"""
res = {}
for word in strs:
temp = [0] * 26
for char in word:
temp[ord(char) - ord('a')] += 1 #temp as key in res
if tuple(temp) not in res:
res[tuple(temp)] = [word]
else:
res[tuple(temp)].append(word)
return res.values()
#return list(res.values())
注意:
上面代码为python2版本,最后返回的是res.values()也就是一个数组
- 但是在python3下运行报错,原因是In Python 3,
dict.values()
(along withdict.keys()
anddict.items()
) returns aview
, rather than a list. See the documentation here. You therefore need to wrap your call todict.values()
in a call tolist.
- 那么最后返回语句应该改为comment out的那一行
438.找到字符串中所有字母异位词
class Solution:
def findAnagrams(self, s: str, p: str):
ans = []
for i in range(0, len(s)):
if self.helper(s[i:len(p) + i], p) is True:
ans.append(i)
return ans
def helper(self, s, t):
temp = [0]*26
for char in s:
temp[ord(char) - ord('a')] += 1
for char in t:
temp[ord(char) - ord('a')] -= 1
return all(x == 0 for x in temp)
- 上面暴力解法超时
- sliding window,follow https://www.youtube.com/watch?v=G8xtZy0fDKg
class Solution:
def findAnagrams(self, s: str, p: str):
if len(p) > len(s):
return []
sCount = {}
pCount = {}
for i in range(len(p)):
if p[i] not in pCount:
pCount[p[i]] = 1
else:
pCount[p[i]] += 1
if s[i] not in sCount:
sCount[s[i]] = 1
else:
sCount[s[i]] += 1
res = [0] if sCount == pCount else []
left = 0
for right in range(len(p), len(s)):
if s[right] not in sCount:
sCount[s[right]] = 1
else:
sCount[s[right]] += 1
sCount[s[left]] -= 1
if sCount[s[left]] == 0:
sCount.pop(s[left])
left += 1
if sCount == pCount:
res.append(left)
return res
349. 两个数组的交集
-
主要考察对于哈希表的运用,有如下两个题解:
class Solution(object):
def intersection(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
return list(set(nums1) & set(nums2))
class Solution(object):
def intersection(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
temp = {}
for num in nums1:
if num not in temp:
temp[num] = 1
print(temp)
ans = []
for num in nums2:
if num in temp and num not in ans:
ans.append(num)
return ans
350. 两个数组的交集 II
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
res = []
temp = {}
for num in nums1:
if num not in temp:
temp[num] = 1
else:
temp[num] += 1
for num in nums2:
if num in temp and temp[num] > 0:
res.append(num)
temp[num] -= 1
return res
202. 快乐数
-
trick:题目中说了会 无限循环,那么也就是说在求和的过程中,sum会重复出现。当需要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。
-
利用哈希表,判断每次更新后的n,如果n在哈希表中出现过,则说明不是快乐数,因为会无限循环下去。接下来继续判断n是否等于1。
-
在写helper 函数的时候不是很熟练,逻辑还是掌握的不熟。
二刷出错点:没有循环起来,没有加 whileTrue:
class Solution(object):
def isHappy(self, n):
"""
:type n: int
:rtype: bool
"""
temp = {}
while True:
n = self.helper(n)
if n == 1:
return True
if n not in temp:
temp[n] = 1
else:
return False
def helper(self, n):
sum = 0
while n > 0:
sum += (n%10)**2
n = n // 10
return sum
1. 两数之和
-
一切的起源(这是力扣的第一题, lol)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashMap = {}
for i in range(len(nums)):
temp = target - nums[i]
if temp not in hashMap:
hashMap[nums[i]] = i
else:
return [i, hashMap[temp]]
总结:
-
可以进一步整理出现哈希碰撞的两种解决方法,DataStructures_Python of Youtube)