# leetcode454.四数相加2
特点:可以重复,不需要去重;四个独立数组
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
dict1 = dict()
dict2 = dict()
ans = 0
for i in nums1:
for j in nums2:
dict1[i+j] = dict1.get(i+j, 0)+1
for i in nums3:
for j in nums4:
dict2[i+j] = dict2.get(i+j, 0)+1
for i in dict1:
target = -i
if target in dict2:
ans += dict1[i] * dict2[target]
return ans
# leetcode383.赎金信
思路:纯字母,使用list,不需要额外构建hashlist
学习:all()函数的使用,all(条件 for i in range(xx)), 当全部条件成立时,返回True
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
# ord()
list_ransom = [0] * 26
list_magazine = [0] * 26
for num in ransomNote:
list_ransom[ord(num)-ord('a')] += 1
for num in magazine:
list_magazine[ord(num)-ord('a')] += 1
#result = [a - b for a, b in zip(list_magazine, list_ransom)]
return all(list_magazine[i] >= list_ransom[i] for i in range(26))
# leetcode15.三数之和
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if not nums or len(nums)<3:
return []
results = []
nums.sort()
for i in range(len(nums)-2):
# 如果a大于0,不需要之后的搜索
if nums[i] > 0:
return results
if i==0 or (i>0 and nums[i] != nums[i-1]):
left = i+1
right = len(nums)-1
while left < right:
sum_ = nums[i]+nums[left]+nums[right]
if sum_ < 0:
left = left+1
elif sum_ > 0:
right = right-1
else:
results.append([nums[i],nums[left],nums[right]])
# 这里要么动left要么动right,否则死循环
# 其实,left right都要动,避免重复
# 必须要动到不等于原来的b和c
'''
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
'''
# 类do while写法
while left<right:
right -= 1
if nums[right] != nums[right+1]:
break
while left<right:
left += 1
if nums[left] != nums[left-1]:
break
return results
# 实现[0,1,1(tar),2,2,2(cur)]将cur移动到tar
# 方法1:
'''
while nums[right] == nums[right-1]: # 这里避免涉及right+1 防止index问题
right -=1
right -= 1
'''
# 方法2:
# 不行,首先要保证left<right
'''
right -= 1
while nums[right] == nums[right+1]:
right -= 1
'''
# 方法3:
'''
while True:
right -= 1
if nums[right] != nums[right+1]:
break
'''
思路:使用双指针的思想,限定条件为:去重;优化为:剪枝
# leetcode18.四数之和
和三数之和一样,最重要的思想为:减枝、去重
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
if not nums or len(nums)<4:
return []
results = []
nums.sort()
for k in range(len(nums)-3):
if nums[k] > target and target > 0:
break
if k>0 and nums[k] == nums[k-1]:
continue
for i in range(k+1, len(nums)-2): # 这里k+1容易写错,不是从1开始
if nums[k]+nums[i] > target and target > 0:
break
# 这里i>k+1容易写错,不是i>1
if i>k+1 and nums[i] == nums[i-1]:
continue
left = i+1
right = len(nums) - 1
while left < right:
sum_ = nums[k]+nums[i]+nums[left]+nums[right]
if sum_ < target:
left = left+1
elif sum_ > target:
right = right-1
else:
results.append([nums[k],nums[i],nums[left],nums[right]])
while left<right:
right -= 1
if nums[right] != nums[right+1]:
break
while left<right:
left += 1
if nums[left] != nums[left-1]:
break
return results
容易写错的点是判断i的遍历范围,以及i的去重。
i是从k+1开始的,不是在sum3中从1开始的。别的基本思想相同。