454. 四数相加 II(dict hash)
题目
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
题目分析
这道题关键是不需要去重,只要i,j,k,l在不同的位置都算成合格
solution
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
# 四个数组1、2、3、4
# 首先遍历前面两个数组1、2记录和以及和出现的次数—>map
# 再遍历后两个数组3、4,得到和c+d,到map中寻找-c-d是否出现以及次数
ab=dict()
for i in nums1:
for j in nums2:
sum_ab=i+j
if sum_ab in ab:#这里需要注意!!!一定要先判断是否在字典中再加计数
ab[sum_ab]+=1
else:
ab[sum_ab]=1
#print(ab)
count=0
for i in nums3:
for j in nums4:
sum_cd=i+j
if (-sum_cd) in ab:
count+=ab[-sum_cd]
else:
continue
return count
时间复杂度
从暴力解法的O(n^4)降到了O(n ^2)
383. 赎金信(array hash)
题目
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
solution
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
# 跟242. 有效的字母异位词类似的解法
arrayhash=[0]*26
for i in magazine:
arrayhash[ord(i)-ord('a')]+=1
#print(arrayhash)
for j in ransomNote:
arrayhash[ord(j)-ord('a')]-=1
for k in arrayhash:
if k<0:
return False
return True
15. 三数之和
题目
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
错误示范版——但我更深层次地理解了set和dict的值必须是无重复的!!!!!
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
count=0
for i in range(len(nums)):
for j in range(i+1,len(nums)):
#print(nums)
sum12=nums[i]+nums[j]
temp=nums.copy()
temp.pop(i)
temp.pop(j-1)
a=[1]*len(temp)
b=dict(zip(temp,a))
print(b,i,j)
# 不能这么做 因为set是必须无重复的 但是temp应该重复的被删掉了!!!
# 也不能换成dict,因为dict的key也必须是无重复的!!!!
if (-sum12) in b:
count+=1
print(count)
solution
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 如果有hash做法的话 会存在很多去重的现象
# 首先对结果进行排序,从小到大
# 遍历nums固定a,然后用双指针left and right
nums.sort()
result=[]
#print(nums)
for i in range(len(nums)-2):
#print(i)
if(i>=1 and nums[i]==nums[i-1]):continue
left=i+1#这里没有判断是否能加 会不会超界(修改了i的范围0~(len-3))
right=len(nums)-1
if nums[i]>0:
continue
while(left<right):
#print(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]])
# b和c的去重在这里
# print(result)
while left<right and nums[left]==nums[left+1]:
left+=1
# 跳出这个循环表示此时的left位上的数字于它的下一位不一样
# 即0,0,2,跳出的时候left在最后一个0位上
while left<right and nums[right]==nums[right-1]:
right-=1
left+=1 #所以最后还要往前走啊啊啊啊笨蛋!!!!
right-=1
return result
要重新做几遍,特别是去重有很多细节!!!!
18. 四数之和(好难,思路沿用三数之和)
这是看完视频写的,注意剪枝和去重的操作!
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
result=[]
nums.sort()
#print(nums)
for i in range(len(nums)):
if nums[i]>0 and target>0 and nums[i]>target:continue # 剪枝
if(i>=1 and nums[i]==nums[i-1]):continue # 去重
for j in range(i+1,len(nums)):
if(nums[i]+nums[j]>0 and target>0 and nums[i]+nums[j]>target):continue #剪枝
if (j>i+1 and nums[j]==nums[j-1]):continue # 去重
#yeyeye!!!聪明蛋!!!j>=1不对!j只能于前一值是j的取值进行比较,所以必须大于i+1
left=j+1
right=len(nums)-1
print(i,j,left,right)
while(left<right):
if (nums[i]+nums[j]+nums[left]+nums[right]>target):
right-=1
elif (nums[i]+nums[j]+nums[left]+nums[right]<target):
left+=1
else:
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
return result