今日任务
● 哈希表理论基础
● 242.有效的字母异位词
● 349. 两个数组的交集
● 202. 快乐数
● 1. 两数之和
详细布置
哈希表理论基础
建议:大家要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map。
什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。 这句话很重要,大家在做哈希表题目都要思考这句话。
文章讲解:https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
242.有效的字母异位词
建议: 这道题目,大家可以感受到 数组 用来做哈希表 给我们带来的遍历之处。
题目链接/文章讲解/视频讲解: https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html
我的思路:
本人对哈希表基本上忘光光,通过看了卡哥的视频捡起知识点。
这题主要是统计两个字符串的字母的个数和种类是否一致,因为只有小写字母所以只需要创建一个26个元素的数组。卡哥的思路就是遍历第一个字符串,统计每个字母出现的个数,然后用第二个循环分别减去数组元素的个数,如果数组最后的每个元素都是0则两个字符串相等。
这里使用record[ord(s[i]) - ord(‘a’)] += 1的方法将a对齐了数组索引0,真的yyds!!!
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
record = [0 for _ in range(26)]
length_s = len(s)
length_t = len(t)
for i in range(length_s):
record[ord(s[i]) - ord('a')] += 1
for i in range(length_t):
record[ord(t[i]) - ord('a')] -= 1
for i in range(26):
if record[i] != 0:
return False
return True
349. 两个数组的交集
建议:本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html
我的思路:
(1)暴力破解
我按照前面哈希的思路,把前面存字母的思路换成存数字,如果存储的两个列表的数字不为0则说明他们有交集,然后用第三个列表append他们的结果。但是这个复杂的地方在于两个列表的长度不一样,同时最大的数字也不一样,需要提前判断,因此我初始化了两个列表来存储个数。最后用第三个列表存储他们的数字。
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
max_num =max(nums1) if max(nums1) >= max(nums2) else max(nums2)
length_1 = [0 for _ in range(max_num+1)]
length_2 = [0 for _ in range(max_num+1)]
for i in range(len(nums1)):
length_1[nums1[i]] += 1
for i in range(len(nums2)):
length_2[nums2[i]] += 1
length_3 = []
for i in range(len(length_1) if len(length_1) > len(length_2) else len(length_2)):
if length_1[i] != 0 and length_2[i] != 0:
length_3.append(i)
return length_3
优化了一下:
思路就是只用一个列表,第二次遍历则遍历nums2的数字在length_1所对应的下表是否为0(因为如果上面不为0则代表nums1中有该数字),不等于0则append到result集合中
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
max_num =max(nums1) if max(nums1) >= max(nums2) else max(nums2)
length_1 = [0 for _ in range(max_num+1)]
for i in range(len(nums1)):
length_1[nums1[i]] += 1
result = set()
for i in range(len(nums2)):
if length_1[nums2[i]] != 0:
result.add(nums2[i])
result = list(result)
return result
(2) 卡哥的思路:
其实和我优化的思路差不多,nums1用哈希表计数,遍历nums2中的值,如果和哈希表上所对应的索引的值不为0则有共同的值,就用另外一个哈希表存储值。
以下提供三个不同的方式
(1)字典
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
dic = {}
for i in range(len(nums1)):
dic[nums1[i]] = dic.get(nums1[i],0) + 1
result = set()
for i in range(len(nums2)):
if nums2[i] in dic:
result.add(nums2[i])
return list(result)
(2)数组
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
count1 = [0 for i in range(1001)]
count2 = [0 for i in range(1001)]
for i in range(len(nums1)):
count1[nums1[i]] += 1
for i in range(len(nums2)):
count2[nums2[i]] += 1
result = []
for i in range(1001):
if count1[i] * count2[i] > 0:
result.append(i)
return result
(3)集合
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.%E5%BF%AB%E4%B9%90%E6%95%B0.html
我的思路
(1)暴力破解
class Solution:
def isHappy(self, n: int) -> bool:
result = []
while True:
sum = 0
n = str(n)
for i in n:
sum += int(i) **2
result.append(sum)
temp = sum
n = temp
if sum == 1:
return True
if len(result) != len(set(result)):
return False
(2)精简
class Solution:
def isHappy(self, n: int) -> bool:
result = []
while n != 1:
n = str(n)
n = sum([int(i) **2 for i in n])
result.append(n)
if len(result) != len(set(result)):
return False
return True
1. 两数之和
建议:本题虽然是 力扣第一题,但是还是挺难的,也是 代码随想录中 数组,set之后,使用map解决哈希问题的第一题。
建议大家先看视频讲解,然后尝试自己写代码,在看文章讲解,加深印象。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.html
我的思路:
(1)暴力破解:
两个for循环遍历,第二个循环往后遍历,如果符合就返回对应的索引。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
for j in range(i+1,len(nums)):
if nums[i] +nums[j] == target:
return [i,j]
(2)卡哥思路:
因为本题,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。
接下来需要明确两点:
- map用来做什么
- map中key和value分别表示什么
map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)
接下来是map中key和value分别表示什么。
这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。
那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。
所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。
在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dic = {}
for i in range(len(nums)):
n = target - nums[i]
if n in dic:
return [dic[n],i]
dic[nums[i]] = i