系列文章目录
代码随想录算法训练营第一天|数组理论基础,704. 二分查找,27. 移除元素
代码随想录算法训练营第二天|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
代码随想录算法训练营第三天|链表理论基础,203.移除链表元素,707.设计链表,206.反转链表
代码随想录算法训练营第四天|24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面试题 02.07. 链表相交,142.环形链表II,总结
代码随想录算法训练营第五天|哈希表理论基础,242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和
454.四数相加II
题目链接: 454.四数相加II
题目内容: 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:0 <= i, j, k, l < n;nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
视频讲解:学透哈希表,map使用有技巧!LeetCode:454.四数相加II
核心思路:
先遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到字典中,然后遍历大C和大D数组,统计0-(c+d) 在dict中出现的情况。
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
record=dict()
for i in range(len(nums1)):
for j in range(len(nums2)):
record[nums1[i]+nums2[j]]=record.get(nums1[i]+nums2[j],0)+1
count=0
for i in range(len(nums3)):
for j in range(len(nums4)):
target=nums3[i]+nums4[j]
if 0-target in record:
count+=record[0-target]
return count
383. 赎金信
题目链接: 383.赎金信
题目内容: 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次
使用数组:
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
ransomNote_count=[0]*26
magazine_count=[0]*26
for i in ransomNote:
ransomNote_count[ord(i)-ord('a')]+=1
for i in magazine:
magazine_count[ord(i)-ord('a')]+=1
return all(ransomNote_count[i]<=magazine_count[i] for i in range(26))
使用字典:
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
record={}
for i in magazine:
record[i]=record.get(i,0)+1
for i in ransomNote:
if i not in record or record[i] == 0:
return False
record[i]-=1
return True
15. 三数之和
题目链接: 15.三数之和
题目内容: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
视频讲解:梦破碎的地方!| LeetCode:15.三数之和
哈希法:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result = []
nums.sort()
# 找出a + b + c = 0
# a = nums[i], b = nums[j], c = -(a + b)
for i in range(len(nums)):
# 排序之后如果第一个元素已经大于零,那么不可能凑成三元组
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i - 1]: #三元组元素a去重
continue
d = {}
for j in range(i + 1, len(nums)):
if j > i + 2 and nums[j] == nums[j-1] == nums[j-2]: # 三元组元素b去重
continue
c = 0 - (nums[i] + nums[j])
if c in d:
result.append([nums[i], nums[j], c])
d.pop(c) # 三元组元素c去重
else:
d[nums[j]] = j
return result
双指针法:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
result=[]
for i in range(len(nums)):
if nums[i] > 0:
return result
if i > 0 and nums[i] == nums[i-1]:
continue
left=i+1
right=len(nums)-1
while left<right:
if nums[left]+nums[right]+nums[i]>0:
right-=1
elif nums[left]+nums[right]+nums[i]<0:
left+=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
left+=1
right-=1
return result
18. 四数之和
题目链接: 18.四数之和
题目内容: 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):0 <= a, b, c, d < n;a、b、c 和 d 互不相同;nums[a] + nums[b] + nums[c] + nums[d] == target;你可以按 任意顺序 返回答案 。
视频讲解:难在去重和剪枝!| LeetCode:18. 四数之和
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
总结
- 一般来说哈希表都是用来快速判断一个元素是否出现集合里;
- 使用哈希法解决问题时,一般会选择如下三种数据结构:数组、set (集合)、map(映射):
- 数组:哈希值比较小,范围也比较小
- set:数值比较大
- map:key,value