代码随想录刷题第六天
哈希表理论基础
Python 哈希表写法
有效字母异位词 (LC 242)
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
示例:
输入: s = “anagram”, t = “nagaram”
输出: true
输入: s = “rat”, t = “car”
输出: false
本题可以使用哈希表来完成对于一个字母出现频率的统计。在python中共有两种不同的哈希表定义方式。一种是通过数组形式(数组index作为key, 数组元素作为value),适用于元素统计范围小(如此题只有26个字母),数组空间可以被定义的题目。还有一种是字典形式,有可供定义的key
和value
.
在本题中,我们使用数组。小写字母硬功只有26个,只需定义一个长度为26的数组
- 遍历第一个字符串,将字符频率统计到数组中
- 遍历第二个字符串, 将第二个字符的频率从数组中删除
- 判断剩下的数组所有元素是否都为零,如是,则返回
True
, 反之,返回False
如何知道字母 “a”
对应0
,字母 “b”
对应1
?
因为ASCII码 "a-z"
是连续递增的, 所以 ord(s[i])-ord("a")
在[0,25]区间中
代码实现:
class Solution(object):
def isAnagram(self, s, t):
table = [0 for _ in range(26)]
for i in range(len(s)):
table[ord(s[i])-ord('a')]+=1
for j in range(len(t)):
table[ord(t[j])-ord('a')]-=1
for k in range(len(table)):
if table[k]!=0:
return False
return True
两个数组的交集 (LC 349)
给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的
这道题同样是考察数字出现的频率,应当使用哈希表。但是这道题很难使用数组,因为nums1
/nums2
中的元素数值<1000,需要创建两个大小为1001的数组来完成频率统计,可以,但是没必要。
这道题可以通过哈希表字典+集合的形式完成。
- 先循环
nums1
,将数组中的元素数值和频率统计在哈希字典中 - 再循环
nums2
,搜索nums2
数组中的元素是否出现在哈希字典中,如果出现了,就放入res
列表中 - 删除重复值,将res转换成set去重,再变回列表输出。
return list(set(res))
代码实现(数组):
class Solution(object):
def intersection(self, nums1, nums2):
table = [0 for i in range(1001)]
res = []
for num in nums1:
table[num]=1
for num in nums2:
if table[num] == 1 and num not in res:
res.append(num)
return res
代码实现(哈希表字典+集合):
class Solution(object):
def intersection(self, nums1, nums2):
table = {}
res = []
for num in nums1:
# table.get用于返回table中的num值
table[num] = table.get(num,0)+1
for num in nums2:
if num in table:
res.append(num)
return list(set(res))
!!!table.get()
table.get()
用于返回table
中num
的值,如果table
中没有num
值,那么返回零。
不可以使用 table[num]+=1
, 因为如果num
不在table
中,无法对没有的key-value
进行操作,KeyError
快乐数(LC 202)
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
示例:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
如果不是快乐数,算法会陷入**“无限循环”**
所以可以使用一个Table(哈希表字典)记录平方和
如果sum
已经在table
中,说明之前已经遇到过这个sum
,算法陷入循环,不为快乐数
如果sum=1
,则是快乐数
难点:如何计算一个数每个数位上的数字的平方和
- 转为
“str”
sum_str = str(sum1)
new_sum = 0
for i in range(len(sum_str)):
new_sum+=int(i)**2
- 使用除法+余数 (divmod)
new_sum = 0
while (sum1 > 0):
sum1, r = divmod(sum1, 10)
new_sum+=r**2
我的代码实现
class Solution(object):
def isHappy(self, n):
table = {}
sum1 = n
while (sum1!=1):
table[sum1] = table.get(sum1,0)+1
if table[sum1]==2:
return False
sum1_str = str(sum1)
sum1=0
for num in sum1_str:
sum1 += int(num)**2
return True
两数之和 (LC 1)
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数
,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
因为题目为两数之和,且每个输入有且只有一个答案,因此不需要考虑去重操作
解题思路:
本题使用字典存储之前遍历过的元素和其索引,元素作为key
,因为算法中要查找的是元素是否出现过,索引(下标)作为value
- 使用一个 for 循环遍历
nums
中所有的元素 need = target-nums[i]
找到需要的另一个数值- 在哈希表中搜索
need
, 查看他是否已经遍历过。如果是,返回当前所以和字典中need
的值 - 将当前数存储在哈希表中,存放已经遍历过的元素
代码实现
class Solution(object):
def twoSum(self, nums, target):
table = {}
for i,num in enumerate(nums):
need = target - num # 需要的另一个数值
if need in table: # 搜索是否遍历过
j = table.get(need)
return [i,j]
table[num] = i # 储存当前遍历过的元素及下表
总结:
今天主要学习了哈希表。在python中共有两种哈希表构建模式,使用数组或者字典。数组一般运用在key在较小范围中,可以准确的定义一个不长的数组,如26个字母等。字典则在其他情况下使用,可以自定义key-value
。在使用字典时,可以使用mapping = defaultdict(int)
将字典初始化成0; 或者使用常规字典mapping = {}
,不初始化数值。 但是要注意的是,当需要统计频率时,如果某一个key没有被初始化时,不可以直接使用mapping[key] = mapping[key]+1
, 因为mapping[key]
还没有被定义,会报错。应该使用mapping[key] = mapping.get(key,0)+1
, 这种方法如果mapping[key]
没有定义,则会返回0
。
mapping.get(key, 0) !!!