哈希表理论基础
哈希表不是数据类型,类似一种解题思想。而这种思想在Python中可以用数组、集合、字典(C++中的说法是map)来实现
感觉这部分代码随想录文字部分讲的不太清楚,在B站看了“动画讲编程”(看动画,5分钟学会最经典的数据结构哈希表,C语言手写实现,不要错过呀_哔哩哔哩_bilibili)辅助理解。
目前的理解:哈希表就是将元素内容,转化为哈希表的下标索引,而将索引变得有意义。因此这种适用数据范围不是很大的题型。
因此在计算元素出现的次数、计数排序(先计算出每个元素出现的次数,再将单一元素进行排序,并考虑元素出现的次数)时非常好用。只需要查询某下标索引对应的元素是数字几,就可得知
将元素内容转化为哈希表的过程,可以通过一个映射关系来完成,这个数学映射关系也就是之前“爱学习的饲养员”提到的哈希算法/哈希函数。
卡哥提到的“当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。”暂时不太理解,需要进一步积累
哈希碰撞感觉只是理解概念,需要结合题目。
242.有效的字母异位词
自刷的记忆还在,关键在于如何把字母转换为数组的下标索引。数组实现哈希表
这里的思路是,a-z共26个字母ASCII码连续。‘a’的ASCII码作为0,则‘z’的为25.出现这就将数组的对应位置的值加1。比较两个字符串最后输出的数组表是否相等即可
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
def calnums(strs):
hashtable = [0]*26
for i in strs:
index = ord(i)-ord('a')#ASCII码转下标索引-->哈希函数
hashtable[index] += 1
return hashtable
hash_s = calnums(s)
hash_t = calnums(t)
return hash_s==hash_t
349. 两个数组的交集
这个碰到我最初的思路是直接用集合的逻辑运算解决。
除了这种方法,卡哥还用了哈希表的方法解决,主要是:
思想是,将遍历数组A,把A转换为哈希表table存储,然后遍历B,把B中出现在table中的元素,重新存储起来。可以用集合实现,也可以用栈来实现。
①用字典实现哈希表(通过哈希表简化数据存储量)
在实现这种方法时,主要困难在字典和集合的基本函数上,总结了好多次了,但是还是记不住……
用到了字典的get函数和del函数( 元素用的是[]而不是() ),熟悉一下语法
遍历数组A,把A转换为哈希表table存储,数字为key,出现次数为value。然后遍历B,如果B中的元素,是table中的键,则将这个元素加入输出结果加入集合/栈
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
hashtable = {}#定义一个空字典
for num in nums1:
# 将num转变为字典的key,出现次数转变为对应value
hashtable[num] = hashtable.get(num,0)+1#get的语法:如果有key=num,则返回对应value,否则返回默认值0
output = []#使用栈来存储交集数据
for num in nums2:
if num in hashtable:#num是字典hashtable中的key
output.append(num)
del hashtable[num]#不删除的话,nums2出现重复元素则会导致output中也重复append
return output
②用数组实现哈希表
和242类似,主要是遍历两个哈希表中的每个元素,如果对应位置的俩元素乘积不为0,则要加入输出的变量中。不再做复现
202.快乐数
如果想到了这个思路就比较简单:把出现过的各位数之和sum_nums存储在一个集合或者数组里,只要新求得的sum_nums在这个集合/数组里出现过了,就证明出现了死循环,否则就一直重复求和过程。
因此关键在于,如何求得各位上的数字的平方和。
两种思路:
①每次除10,每次得到个位数r,将r^2相加知道除10后的十位≠0
②讲数字转str以将各个位上的数字分开(很巧妙)
因为对集合的各个函数不太熟练,因此只尝试用集合实现,数组的(栈实现)暂不尝试。
class Solution:
def isHappy(self, n: int) -> bool:
def get_sum(n) :
sum_nums = 0
while n:#一直循环到n=0,求n所有位上的数的平方和
n,r = divmod(n,10)#每次除10,则依次得到每一位上的数字
sum_nums += r**2
return sum_nums
sum_set = set()
while 1:
sum_nums = get_sum(n)
if sum_nums==1:
return sum_nums==1
else:
if sum_nums in sum_set:
return sum_nums==1
else :
sum_set.add(sum_nums)
n = sum_nums
1.两数之和
同样难的是思路。感觉哈希表的用途还是在:原本比如是一个数组,每次只能获取一个信息。但转换为哈希表后,不管是索引还是存储的值都是具有意义的,那么同时可以获取两个信息--->将下标索引变得有意义。
或者是通过哈希函数这种映射关系,将原来的数据简化为只存储我们想要的信息,方便快速查询。
这个题的思路是用字典实现哈希表,选择key=num,而num对应的index作为value的原因是字典的查询是通过key来查询的。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
record = {}#建立一个字典
for i in range(len(nums)):
another_num = target-nums[i]
if another_num in record and record[another_num]!=i:#另一半数已经出现过,且索引不是目前这个索引
return [i,record[another_num]]
record[nums[i]] = i