● 454.四数相加II
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
hash={}
for i in nums1:
for j in nums2:
if i+j not in hash:
hash[i+j]=1
else:
hash[i+j]+=1
res=0
for k in nums3:
for l in nums4:
if 0-k-l in hash:
res+=hash[0-k-l]
return res
● 383. 赎金信
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
hash1={}
for i in magazine:
if i not in hash1:
hash1[i]=1
else:
hash1[i]+=1
for i in ransomNote:
if i not in hash1:
return False
else:
hash1[i]-=1
if hash1[i]<0:
return False
return True
● 15. 三数之和
关键在于去重
法一:哈希法
两重for 循环,一重便利a,一重便利b,再寻找0-a-b,用哈希没有顺序,去重会比较麻烦。
法二:双指针
for 循环遍历i,得到a
left,right
对数组进行排序,没有要求返回下标,所以可以排序。
如果nums[i]+nums[left]+nums[right]>0,right往左移一位
<0 ,left往右移
==0,得到num[i],nums[left],nums[right]
难点:去重
i,left,right可能有重复值,所以需要去重。
代码实现
result=[] 存放结果集
sort()排序
if nums[i]>0 return
难点:判断nums[i]==nums[i+1] continue,结果集中有重复会直接跳过
例如[-1,-1,2]不在结果集中
还是nums[i]==nums[i-1] continue,left,right不受影响
elif i>0 and nums[i]==nums[i-1] (对a的去重)
continue
left=i+1
right=len(n)-1
while right>left 边界问题尝试带入,right=left,说明b和c为同一个值
0 -1 -1 -1 1 1 1
得到的结果集仍然需要去重,收获结果集后面
if right>left right[i]==right[i-1] right-=1 (对c的去重)
if right>left left[i]==left[i+1] left+=1 (对b的去重)
持续向中间移动
结果集0000
放在 while left <right 后面会无法收获结果集
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result=[]
nums.sort()
n=len(nums)
for i in range(n):
left=i+1
right=n-1
if nums[i]>0:
return result
if i>0 and nums[i]==nums[i-1]:
continue
while left<right:
if nums[i]+nums[left]+nums[right]>0:
right-=1
elif nums[i]+nums[left]+nums[right]<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
right-=1
left+=1
return result
18.四数之和
比三数之和再套一层循环k
for k
for i
left,right
剪枝和去重是难点
如何对k进行剪枝:
nums[i]>target 剪枝:错误,两个负数相加可能会变得更小。
-4,-1,0,0 target=-5
if nums[k]>target and nums[k]>0 and target>0:break
去重:
if k>0 and nums[k]==nums[k-1]: continue
for i=k+1
同样可以剪枝
nums[k]+nums[i]是一个整体
因此nums[k]+nums[i]>targrt and nums[k]+nums[i]>0 and arget>0:break
去重:
if i>k+1 (因为i=k+1开始的)and nums[i]==numd[i-1]:continue
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
result = []
nums.sort()
for i in range(len(nums)):
# 如果第一个元素已经大于0,不需要进一步检查
if nums[i]>target and nums[i] > 0 and target>0 :
break
# 跳过相同的元素以避免重复
if i > 0 and nums[i] == nums[i - 1]:
continue
for k in range (i+1,len(nums)):
if nums[i]+nums[k]>target and nums[i]+nums[k]>0 and target>0:
break
if k>i+1 and nums[k] == nums[k - 1]:
continue
left = k + 1
right = len(nums) - 1
while right > left:
sum_ = nums[i] + nums[k]+nums[left] + nums[right]
if sum_ < target:
left += 1
elif sum_ > target:
right -= 1
else:
result.append([nums[i], nums[k],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