Day 6
今日任务
● 哈希表理论基础
● 242.有效的字母异位词
● 349. 两个数组的交集
● 202. 快乐数
● 1. 两数之和
详细布置
哈希表理论基础
建议:大了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map。
知识点:
什么时候想到用哈希法:当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
文章讲解:https://programmercarl.com/哈希表理论基础.html
242.有效的字母异位词
建议: 这道题目,大家可以感受到数组 用来做哈希表给我们带来的遍历之处。
题目链接/文章讲解/视频讲解: https://programmercarl.com/0242.有效的字母异位词.html
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
count = [0]*26
for l1 in s:
count[ord(l1) - ord('a')] += 1
for l2 in t:
count[ord(l2) - ord('a')] -= 1
for i in range(26):
if count[i] != 0:
return False
return True
349. 两个数组的交集
建议:本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0349.两个数组的交集.html
知识点:
哈希表:最擅长解决→给你一个元素,判断在这个集合中是否出现过
**具体用哪个:数组 or set or 哈希表?
数值很大,用数组就不合适了,需要用set
数值可能不是很大,但数值分布很分散(大得很大,小的很小,小的到大增长很快那种),这种情况下用数组会浪费很多存储空间。这种情况下用set更合适
c++中:set and multi-set底层实现是红黑树 unordered set底层实现是使用哈希值的方式
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
# 使用哈希表存储一个数组中的所有元素
table = {}
for num in nums1:
table[num] = table.get(num, 0) + 1
# 使用集合存储结果
res = set()
for num in nums2:
if num in table:
res.add(num)
del table[num]
return list(res)
用一个哈希表(字典)记录第一个数组中的元素,然后遍历第二个数组,找出共同的元素,并用集合保存,去重。
👉 创建一个空字典 table,用来记录 nums1 中每个数的出现次数(其实这里只需要记录是否存在,但这里用了计数的写法)。
👉 遍历 nums1:
如果 num 已在字典中,table.get(num, 0) 就会取它的值。
如果不在字典中,get 会返回 0。
然后 +1,更新到字典里。
例:
假设 nums1 = [1, 2, 2, 3],
那么遍历完后:
table = {1:1, 2:2, 3:1}
用数组:
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
count1 = [0]*1001
count2 = [0]*1001
result = []
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
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return list(set(nums1) & set(nums2))
202. 快乐数
建议:这道题目也是set的应用,其实和上一题差不多,就是套在快乐数一个壳子
题目链接/文章讲解: https://programmercarl.com/0202.快乐数.html
class Solution:
def isHappy(self, n: int) -> bool:
seen = set()
while n != 1:
n = sum(int(i) ** 2 for i in str(n))
if n in seen:
return False
seen.add(n)
return True
1. 两数之和
建议:本题虽然是 力扣第一题,但是还是挺难的,也是 代码随想录中 数组,set之后,使用map解决哈希问题的第一题。建议先看视频讲解,然后尝试自己写代码,再看文章讲解,加深印象。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0001.两数之和.html
知识点:
会想到用哈希法/用哈希法作映射→每当遇到要判断这个元素是否出现过
通过判断target - cur我们是否之前遍历过来找到符合题意的结果
需要存放2个元素:元素 + 下标
用map 用数值 而非下标 去作为key
原因:我们是要查找一个元素是否出现过 而map可以在最快的时间内查找这个key是否在map里出现过 因此元素作为key
map在题目中用来存放我们遍历过的元素
双指针法:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
sorted_nums = sorted(nums)
left,right=0,len(nums)-1
while left < right:
if sorted_nums[left] + sorted_nums[right] < target:
left += 1
elif sorted_nums[left] + sorted_nums[right] > target:
right -= 1
else:
left_index = nums.index(sorted_nums[left])
right_index = nums.index(sorted_nums[right])
if left_index == right_index:
right_index = nums[left_index+1:].index(sorted_nums[right]) + left_index + 1
return [left_index, right_index]
体现c++解法的map思想
#使用集合
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
#创建一个集合来存储我们目前看到的数字
seen = set()
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [nums.index(complement), i]
seen.add(num)
#使用字典
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
records = dict()
for index, value in enumerate(nums):
if target - value in records: # 遍历当前元素,并在map中寻找是否有匹配的key
return [records[target- value], index]
records[value] = index # 如果没找到匹配对,就把访问过的元素和下标加入到map中
return []