哈希表part01(24.01.01)
安排:先独立做题,然后看视频讲解,然后看文章讲解,然后再重新做一遍题,把题目AC,最后整理成今日当天的博客。
学习时长:四小时
学习内容:自己尝试+pdf说明+视频+力扣题解+自己默写
学习感悟:需要看一下python版的数据结构课本了!
哈希表理论基础
1.什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。 这句话很重要,大家在做哈希表题目都要思考这句话。
2.哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。
3.哈希表是根据关键码的值而直接进行访问的数据结构。(直白来讲其实数组就是一张哈希表。)
4.hash function ,也就是哈希函数。哈希函数如下图所示,通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。
5.如果hashCode得到的数值大于哈希表的大小,也就是大于tableSize了,怎么办呢?(不再是单射),这种现象被称为哈希碰撞。
一般哈希碰撞有两种解决方法, 拉链法和线性探测法。
- 拉链法:发生冲突的元素都被存储在链表中。
- 线性探测法:
一定要保证tableSize大于dataSize。(把冲突的多出来的数据放在哈希表的空位中。)
6.常见的三种哈希结构:数组(哈希表size比较小的时候,可以用二十六个字母来表示)、集合set(size比较大的时候)、映射map(k对应value的时候用map)
7.但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
242.有效的字母异位词
题目链接:力扣题目链接
笔记:
1.我们可以统计s 各字符时执行 +1 ,统计 t 各字符时 −1 。
2.代码中涉及到‘a’,是作为一个固定的参照物,依据各个字母的相对偏差来定位。ord()函数是一个内建函数,用于返回一个表示给定字符的 Unicode 字符的整数。
提交代码:
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
record = [0]*26
for i in s:
#并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
record[ord(i)-ord('a')] += 1
for i in t:
record[ord(i)-ord('a')] -= 1
for i in range(26):
if record[i] != 0:
return False
return True
ord(i)
被用于获取字符串中每个字符的 Unicode 码点,然后通过减去 ord("a")
来得到相对于小写字母 'a' 的偏移量,以便在数组或列表中记录字母的频率。
349. 两个数组的交集
题目链接:力扣题目链接
笔记:
1.可以用数组做,也可以用set做。(set方法没懂,先跳了)
2.集合添加元素用.add,数组添加元素用.append
提交代码:
class Solution: #用数组方法做
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
result = []
count1 = [0]*1001
count2 = [0]*1001
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. 快乐数
题目链接:力扣题目链接
笔记:
1. 题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。判断sum是否重复出现就可以使用unordered_set。
2.某整数的各位数字求和,可以将整数转换为字符串,以便逐个访问数字:遍历每位字符并转成整数。
提交代码:
class Solution:
def isHappy(self, n: int) -> bool:
result = set()
while n not in result:
result.add(n)
sum = 0
n_str = str(n)
for i in n_str:
sum += int(i)**2
if sum == 1:
return True
else:
n = sum
return False
1. 两数之和
题目链接:力扣题目链接
笔记:
1.本题我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。
2.使用数组和set来做哈希法的局限:数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
3.这道题我们需要给出一个元素(=target-此处的元素),判断这个元素是否出现过,如果出现过,返回这个元素的下标。
4.enumerate()
是一个 Python 内置函数,它返回一个包含元素索引和元素值的迭代器。nums.index() 返回对应元素的索引
提交代码:前几天自己提交了暴力求解版本(两层循环嵌套)
class Solution: #暴力法
def twoSum(self, nums: List[int], target: int) -> List[int]:
i=0
l=len(nums)
while i < l:
for j in range(i+1,l):
if nums[j] != target-nums[i]:
j += 1
else:
return i,j
i += 1
class Solution: #哈希法
def twoSum(self, nums: List[int], target: int) -> List[int]:
record = set()
for i, num in enumerate(nums):
complement = target - num
if complement in record:
return [nums.index(complement),i]
else:
record.add(num)
好像python的数据结构和c++的不一样,没有unordered_set, unordered_map这种东西,这节学的迷迷糊糊的...