目录
242. 有效的字母异位词
题目链接:242. 有效的字母异位词 - 力扣(LeetCode)
文章讲解:代码随想录
解题卡点:没想到使用数组和默认字典,使用了更麻烦的普通字典
统计s的字母个数和出现次数,再使用t进行比较即可。
可使用长度[0]*26的数组,数组也是简单的哈希表,遍历s字母出现一次+1,再遍历t字母出现一次-1,通过这种方式在一个数组上统计s和t的信息。如果是字母异位词,操作完后数组应为26个0。
也可使用defaultdict,相较普通dict的好处是,在某个字母第一次出现时,可以直接写入字典,不用额外判断。
# 解法1:使用1个数组
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
st_list = [0]*26
anagram_list = [0]*26
for i in s:
st_list[ord(i) - ord('a')] += 1
for j in t:
st_list[ord(j) - ord('a')] -= 1
return st_list == anagram_list
# 解法2:使用2个默认字典
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
from collections import defaultdict
s_dict = defaultdict(int)
t_dict = defaultdict(int)
for i in s:
s_dict[i] += 1
for j in t:
t_dict[j] += 1
return s_dict == t_dict
# 时间复杂度 O(n+m) n和m为字符串s和t的长度
# 空间复杂度 O(1) (将字符集大小视为常数,如ASCII字符集中,字符集大小为128)
349. 两个数组的交集
题目链接:349. 两个数组的交集 - 力扣(LeetCode)
文章讲解:代码随想录
解题卡点:实现输出结果中元素唯一时,不清楚哪些内置函数是可以用的
分别统计两个nums的数字个数与出现次数,进行比较得到交集。使用set可以大大简化去重操作,故下面写出了两个不使用set的方法。
①使用数组。使用数组做哈希题目的条件:限制了数值大小,哈希值跨度较小比较集中。本题中除了统计nums的循环外,还使用了遍历结果的第三个循环来实现去重操作。
②使用字典。在判断nums2元素在不在nums1中时,若在则将元素加入结果列表,同时删除nums1字典中的该元素,实现去重操作。
Tips:
哈希问题都用set可行么?不行,直接使用set不仅占用空间比数组大,而且速度要比数组慢。
# 解法1:只使用数组
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
count1 = [0]*1001
count2 = [0]*1001
res = []
for i in nums1:
count1[i] += 1
for j in nums2:
count2[j] += 1
for k in range(1001):
if count1[k]*count2[k] > 0:
res.append(k)
return res
# 解法2:只使用字典
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
from collections import defaultdict
intersection_dict = defaultdict(int)
res = []
for i in nums1:
intersection_dict[i] += 1
for j in nums2:
if j in intersection_dict:
res.append(j)
del(intersection_dict[j]) # 第一次出现并删除字典中该元素后,第二次遇见时就不会重复统计了
return res
# 时间复杂度 O(n+m) n和m为数组nums1和nums2的长度
# 空间复杂度 O(n)
202. 快乐数
文章讲解:代码随想录
解题卡点:何时以及如何停止循环
我的思路:递归计算各位上平方和,把本题的哈希考点误以为是制作数字平方表,没有理解解题的真正思路。
class Solution:
def __init__(self):
self.count = 1 # 控制递归次数
self.num_square = {i: i**2 for i in range(10)} # 制作数字的平方表,后续直接查表
def calculate(self, num): # 递归函数,计算数字各位上的平方和
if self.count > 100: # 递归100次则退出递归
return False
if num == 1: # 各位上平方和为1则退出递归
return True
else:
total = 0
for i in str(num):
total += self.num_square[int(i)]
num = total
self.count += 1
return self.calculate(num)
def isHappy(self, n: int) -> bool:
return self.calculate(n)
解答思路:记录每一次的各位上平方和,若和为1则是开心数,若和出现重复则该数进入无限循环得不到1,返回False。
class Solution:
def isHappy(self, n: int) -> bool:
calculate_rec = set()
while n != 1:
n = sum(int(i)**2 for i in str(n))
if n in calculate_rec:
return False
calculate_rec.add(n)
return True
# 时间复杂度 O(logn)
# 空间复杂度 O(logn)
# 复杂度计算见 每日精华
1. 两数之和
文章讲解:代码随想录
解题卡点:想不到这题和哈希有什么关联
什么时候使用哈希法:当需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
本题需要一个哈希表存放遍历过的元素,然后在遍历数组时查询是否存在某元素与当前元素相加等于target,若存在返回下标。需要知道元素对应的下标,故使用字典作为哈希。
先判断该元素的之前元素有没有符合条件的,若没有再将当前元素添加到字典中。若顺序颠倒,遇上[3, 3] target=6会出问题。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
num_rec = dict()
for idx, val in enumerate(nums):
num_need = target - val
if num_need in num_rec:
return [idx, num_rec[num_need]]
num_rec[val] = idx
# 时间复杂度 O(n)
# 空间复杂度 O(n)
本题有四个重点需思考清楚:
①为什么想到使用哈希表
②为什么使用字典作为哈希表
③字典是用来存什么的
④字典中的key和value是用来存什么的