代码随想录算法训练营第七天 | 454.四数相加 383.赎金信 15.三数之和 18.四数之和
454.四数相加
题目:给你四个整数数组 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,key为a+b,value为出现次数。再遍历k、l寻找0-a-b。
关键:
- 遍历1、2数组并记录record时,区分次数+1还是=1;
- 遍历3、4数组时,找到对应的key来统计对应的value,是相加而不是相乘!!两个哈希才相乘
报错:for i in nums1:而不是range(len(nums1)),遍历数值而不是下标。
点击查看代码
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
record={}
count=0
for i in nums1:
for j in nums2:
if i+j in record:
record[i+j]+=1
else:
record[i+j]=1
for k in nums3:
for l in nums4:
if 0-k-l in record:
count+=record[0-k-l]
return count
383.赎金信
题目:给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
解题:
思路:和242.有效的字母异位词很像,我就学习了那个的写法,区别就是242要全=0才满足题意,这儿只要不小于0就可以了。一个哈希表就够用了~
一、
点击查看代码
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
record_m=[0]*26
for i in magazine:
record_m[ord(i)-ord('a')]+=1
for j in ransomNote:
record_m[ord(j)-ord('a')]-=1
for k in range(26):
if record_m[k]<0:
return False
return True
二、用count()数每个字符出现的次数,记得set(ransomNote)转化成哈希表,这个能打败99.79%!
点击查看代码
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
return all(ransomNote.count(c) <= magazine.count(c) for c in set(ransomNote))
15.三数之和
题目:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
解题:
思路:哈希表解决去重太费时难考虑全,且是在一个数组里找三元组,适合双指针。
遍历i,同时定义left=i+1,right=len(nums)-1,通过比较三个数之和,>0,right左移,<0,left右移。
关键:
- 对a去重,判断nums[i]与nums[i-1]是否相同,因为三元组内的元素是可重复的;
- 对b、c去重,应该放在找到一个三元组后,sum=0部分
报错:
- 用elif不是if,避免错误分支进入;
- if i > 0 and...:和while right > left and...:都不能落下这个一个条件,避免越界访问nums[i-1]即nums[-1]
点击查看代码
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result=[]
nums.sort()
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 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
left+=1
right-=1
return result
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
你可以按 任意顺序 返回答案 。
解题:
思路:三数之和之外再加一层遍历。剪枝懒得看了不用也能过。
点击查看代码
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
result=[]
nums.sort()
for i in range(len(nums)):
if i>0 and nums[i]==nums[i-1]:
continue
for j in range(i+1,len(nums)):
if j>i+1 and nums[j]==nums[j-1]:
continue
left=j+1
right=len(nums)-1
while right>left:
sum=nums[i]+nums[j]+nums[left]+nums[right]
if sum<target:
left+=1
elif sum>target:
right-=1
else:
result.append([nums[i],nums[j],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
心得:
IndentationError: unindent does not match any outer indentation level 缩进问题
SyntaxError: 'return' outside function 缩进空格问题