1.哈希表(hash table)基础
之前没有对哈希表做过系统性的学习,现在各部分主要内容截图下,方便以后自己翻阅查找。
1)定义
2)哈希函数
3)哈希碰撞
因为储存时候出现两个以上的数值映射到同一个位置上,就产生了哈希碰撞,不过哈希碰撞是可以解决的,可以用拉链法和线性试探法。
拉链法
线性探测法
3)常见哈希结构
- 数组
- set(集合)
- map(映射)-py里面竟然是dict (字典)
py中的set为无序的不可重复的key。
字典包含key和value
2.数组作为哈希表(242、383、49、438)
242. 有效的字母异位词 - 力扣(LeetCode) (leetcode-cn.com)
class Solution(object):
def isAnagram(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
if len(s) !=len(t): return False
hash= [0]*26
for i in range(len(s)):
hash[ord(s[i])-ord('a')]+=1
hash[ord(t[i])-ord('a')]-=1
if any ([_ for _ in hash]):return False
else : return True
383. 赎金信 - 力扣(LeetCode) (leetcode-cn.com)
class Solution(object):
def canConstruct(self, ransomNote, magazine):
"""
:type ransomNote: str
:type magazine: str
:rtype: bool
"""
array= [0]*26
for i in magazine: #+1
array[ord(i)-ord('a')]+= 1
for i in ransomNote: #-1
array[ord(i)-ord('a')]-= 1
if any([_<0 for _ in array]):return False
else: return True
49. 字母异位词分组 - 力扣(LeetCode) (leetcode-cn.com)
应用了字典,
class Solution(object):
def groupAnagrams(self, strs):
"""
:type strs: List[str]
:rtype: List[List[str]]
"""
dic, ls ={}, [] #从小到排列的字符串作为key 原始的字符串作为value
for s in strs:
ls= ''.join(sorted(s))
if ls in dic: #注意不要再dic.value 里面寻找 这样会很慢 可以直接在dic里面寻找
dic[ls].append(s)
else:
dic[ls]=[s]
return list(dic.values())
438. 找到字符串中所有字母异位词 - 力扣(LeetCode) (leetcode-cn.com)
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
n, m, res = len(s), len(p), []
if n < m: return res
pCnt = [0] * 26
sCnt = [0] * 26
for i in range(m): #初始窗口
pCnt[ord(p[i])-ord('a')]+=1
sCnt[ord(s[i])-ord('a')]+=1
if sCnt == pCnt: res.append(0)
for i in range(m,n):
sCnt[ord(s[i-m])-ord('a')]-=1 #移动窗口
sCnt[ord(s[i])-ord('a')] +=1
if sCnt == pCnt: res.append(i-m+1)
return res
350. 两个数组的交集 II - 力扣(LeetCode) (leetcode-cn.com)
很意外竟然可以这样
class Solution(object):
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
#用数组
array = [0]*1000 #代表0-1000
res=[]
for i in nums1:array[i] +=1
for i in nums2:
if array[i] :
array[i] -=1
res.append(i)
return res
2.集合作为哈希表(349、202)
349. 两个数组的交集 - 力扣(LeetCode) (leetcode-cn.com)
class Solution(object):
def intersection(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
'''
set1= set(nums1)
set2= set()
for i in nums2:
if i in set1 and i not in set2:
set2.add(i)
return list(set2)
'''
return list(set(nums1)& set(nums2))
202. 快乐数 - 力扣(LeetCode) (leetcode-cn.com)
class Solution(object):
def isHappy(self, n):
"""
:type n: int
:rtype: bool
"""
collet=set([n])
while 1:
sum=0 #%题设的循环计算
while n:
sum+= (n%10)**2
n=n//10
n=sum
if n==1: return True #快乐数
elif n not in collet: collet.add(n)
else: return False #出现重复 不是快乐数
2.map(dict)作为哈希表(1、)
1. 两数之和 - 力扣(LeetCode) (leetcode-cn.com)
```python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: dic= dict() for idx, value in enumerate(nums): #获取索引和数值 if target- value not in dic: dic[value] =idx else: return [dic[target- value], idx] ``` [454. 四数相加 II - 力扣(LeetCode) (leetcode-cn.com)](https://leetcode-cn.com/problems/4sum-ii/submissions/) 四数相加可以分别分成两个,前面两个数和只需要表示出现的次数即可,因为是要求出现的次数。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2de4d7925c894cd59e3ea6a207c26ce8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyX6aOO6aOO,size_20,color_FFFFFF,t_70,g_se,x_16)class Solution:
def fourSumCount(self, nums1: list[int], nums2: list[int], nums3: list[int], nums4: list[int]) -> int:
hashmap= dict()
for i in nums1: #将前两个数相加和作为key value表示出现的次数
for j in nums2:
sumls= i+j
if sumls in hashmap:
hashmap[sumls]+= 1
else:
hashmap[sumls] = 1
count=0
for i in nums3: #将后面两个数取相加负,看是否等于hash的key,如果等于计数加上出现的value
for j in nums4:
sumls= -i-j
if sumls in hashmap:
count+= hashmap[sumls]
return count
3.双指针操作
15. 三数之和 - 力扣(LeetCode) (leetcode-cn.com)
乱入双指针操作。。
class Solution:
def threeSum(self, nums: list[int]) -> list[list[int]]:
#双指针法
nums.sort()
res=set()
n= len(nums)
for i in range(n):
if nums[i] > 0:break
if i >= 1 and nums[i] == nums[i- 1]:continue
left, right = i+1, n-1
while left < right :
if nums[left] +nums[right] +nums[i]> 0:
right-= 1
elif nums[left] +nums[right] +nums[i]< 0:
left+= 1
else:
#if [nums[i],nums[left],nums[right]] not in res:
res.add((nums[i],nums[left],nums[right])) #用集合加元组消除重复
right-= 1
left+= 1
return [list(_) for _ in res]
18. 四数之和 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
#双指针法
nums.sort()
res=set()
n= len(nums)
for i in range(n):
if nums[i] > target//4:break #最小的数值大于平均值 是要跳出循环的
if i >= 1 and nums[i] == nums[i- 1]:continue #当前数为前面的重复数
for j in range(i+1,n):
left, right = j+1, n-1
while left < right :
if nums[left] +nums[right] +nums[i]+nums[j]> target:
right-= 1
elif nums[left] +nums[right] +nums[i]+nums[j]< target:
left+= 1
else:
res.add((nums[i],nums[j],nums[left],nums[right])) #用集合加元组消除重复
right-= 1
left+= 1
return [list(_) for _ in res]
4.总结
需要快速索引的,可以用哈希表,哈希表有三种,数组,set(集合),map(dict字典)