哈希表part02(24.01.02)
安排:先独立做题,然后看视频讲解,然后看文章讲解,然后再重新做一遍题,把题目AC,最后整理成今日当天的博客。
学习时长:三个半小时
学习内容:自己尝试+pdf说明+视频+力扣题解+自己默写
学习感悟:渐入佳境!
454.四数相加II
题目链接:力扣题目链接
笔记:
1.四个数组两两分组,分别进行元素遍历加和(大A和大B,大C和大D)。key放a和b两数之和,value 放a和b两数之和出现的次数。将和以及次数放入哈希表,在对C和D遍历时在哈希表中查找是否含有0-(c+d)。
2.在 Python 中,字典是一种键-值对(key-value pair)的数据结构,而 dict()
是用来创建一个空字典的构造函数。
3.在 Python 字典(hashmap
)中统计键值对应的出现次数的常见写法:hashmap.get(n1+n2, 0)
是获取字典中键为 n1 + n2
的值,如果该键不存在则返回默认值 0。hashmap[n1 + n2] = hashmap.get(n1 + n2, 0) + 1
将字典中键为 n1 + n2
的值加 1,相当于统计了 n1 + n2
出现的次数。
提交代码:
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
hashmap = dict()
for a in nums1:
for b in nums2:
hashmap[a+b] = hashmap.get(a+b,0)+1
count = 0
for c in nums3:
for d in nums4:
key = 0-c-d
if key in hashmap:
count += hashmap[key]
return count
383. 赎金信
题目链接:力扣题目链接
提交代码:
class Solution: #自己尝试按字母异位词的思路写了一版
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
count = [0]*26
for i in ransomNote:
count[ord(i)-ord('a')] += 1
for j in magazine:
count[ord(j)-ord('a')] -= 1
for k in range(26):
if count[k] > 0:
return False
return True
15. 三数之和
题目链接:力扣题目链接
笔记:
哈希表中去重比较麻烦,所以本题不用哈希法。本题比较好理解的一个方法是双指针法,重点在于对结果进行去重。首先对整个数组进行一个排序,nums.sort()
是一个用于对列表 nums
进行排序(按升序)的方法。
提交代码:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result = []
nums.sort()
for i in range(len(nums)):
# 如果第一个元素已经大于0,不需要进一步检查
if nums[i] > 0:
return result
# 跳过相同的元素以避免重复
if i > 0 and nums[i] == nums[i - 1]:
continue
left = i + 1
right = len(nums) - 1
while right > left:
sum_ = nums[i] + nums[left] + nums[right]
if sum_ < 0:
left += 1
elif sum_ > 0:
right -= 1
else:
result.append([nums[i], nums[left], nums[right]])
# 跳过相同的元素以避免重复
while right > left and nums[right] == nums[right - 1]:
right -= 1
while right > left and nums[left] == nums[left + 1]:
left += 1
right -= 1
left += 1
return result
过程中报错:
1.if语句中return是直接跳出循环得到最终结果了,continue则是跳出本轮循环,接着下一轮循环。
2.注意别漏下right>left 的约束!!
18. 四数之和
题目链接:力扣题目链接
笔记:
1.思路上延续三数之和的做法,在外层再嵌套一个for循环即可。重点在于循环的剪枝和去重方面有一些区别。比如说排序后第一个元素>target并不意味着要直接剪掉,因为会出现负数,所以会出现越加越小的情况。
2.由于有两层for循环,所以有两级的剪枝和去重操作。
提交代码:
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
n = len(nums)
result = []
for i in range(n):
if nums[i] > target and nums[i] > 0 and target > 0:# 剪枝(可省)
break
if i > 0 and nums[i] == nums[i-1]:# 去重
continue
for j in range(i+1, n):
if nums[i] + nums[j] > target and target > 0: #剪枝(可省)
break
if j > i+1 and nums[j] == nums[j-1]: # 去重
continue
left, right = j+1, n-1
while left < right:
s = nums[i] + nums[j] + nums[left] + nums[right]
if s == target:
result.append([nums[i], nums[j], nums[left], nums[right]])
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
elif s < target:
left += 1
else:
right -= 1
return result
过程中报错:
注意left+1和right-1写在循环的哪里(只有分类讨论sum==target的时候才对二者同时进行操作)