917 字
5 分钟
代码随想录算法训练营第六天 | 哈希表 Part02

哈希表 Part02 笔记#


454. 四数相加 II#

LeetCode 454. 四数相加 II

class Solution:
# 四数字相加问题可以转化为两个两数相加的问题
# 即将 nums1 和 nums2 的所有两数之和存入一个哈希表中,nums3 和 nums4 的所有两数之和则需要查找哈希表中是否存在对应的负数和
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
record = {}
# 计算 nums1 和 nums2 的所有两数之和,并记录出现的次数
for num1 in nums1:
for num2 in nums2:
record[num1 + num2] = record.get(num1 + num2, 0) + 1
res = 0
# 对于 nums3 和 nums4 的每一对数字,计算它们的和,并查找哈希表中是否存在对应的负数和
for num3 in nums3:
for num4 in nums4:
need = 0 - (num3 + num4)
if need in record:
res += record[need]
return res

383. 赎金信#

LeetCode 383. 赎金信

class Solution:
# 这个是和 LeetCode 242 有效的字母异位词 类似的题目
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
record = {}
# 统计 magazine 中每个字母出现的次数
for char in magazine:
record[char] = record.get(char, 0) + 1
# 遍历 ransomNote 中的每个字符,依次判断是否可以匹配
for char in ransomNote:
if char in record and record[char] > 0:
record[char] -= 1
else:
return False
return True

15. 三数之和#

LeetCode 15. 三数之和

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort() # 排序后方便使用双指针和去重
res = []
for i in range(len(nums) - 2):
left = i + 1
right = len(nums) - 1
# 如果当前数字大于0,则后续的数字都大于0,无法满足三数之和为0
if nums[i] > 0:
break
# ⚠️ 注意这里需要跳过重复的数字,避免结果中出现重复的三元组
if i > 0 and nums[i] == nums[i - 1]:
continue
while left < right:
total = nums[i] + nums[left] + nums[right]
if total == 0:
res.append([nums[i], 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 total < 0:
left += 1
else:
right -= 1
return res

18. 四数之和#

LeetCode 18. 四数之和

class Solution:
# 四数之和可以转化为三数之和的问题
# 首先对数组进行排序,然后固定前两个数字,使用双指针查找后两个数字
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort() # 排序以便使用双指针法
res = []
for i in range(len(nums) - 3):
# 如果当前数字加上后三个最小的数字的和都大于目标值,则直接跳出循环
if nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target:
break
# 如果当前数字加上后三个最大的数字的和都小于目标值,则跳过当前数字
if nums[i] + nums[-1] + nums[-2] + nums[-3] < target:
continue
if i > 0 and nums[i] == nums[i - 1]:
continue
for j in range(i + 1, len(nums) - 2):
# 如果当前数字加上后面两个最小的数字的和都大于目标值,则跳出循环
if nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target:
break
# 如果当前数字加上后面两个最大的数字的和都小于目标值,则跳过
if nums[i] + nums[j] + nums[-1] + nums[-2] < target:
continue
if j > i + 1 and nums[j] == nums[j - 1]:
continue
left = j + 1
right = len(nums) - 1
while left < right:
total = nums[i] + nums[j] + nums[left] + nums[right]
if total == target:
res.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 total > target:
right -= 1
else:
left += 1
return res
代码随想录算法训练营第六天 | 哈希表 Part02
https://fuwari.vercel.app/posts/code_musings_day_six/
作者
Jarrett
发布于
2025-06-17
许可协议
CC BY-NC-SA 4.0