454. 4Sum II
先两层遍历数组num1
和num2
,用哈希表记录a+b
出现的次数; 再遍历num3
、num4
数组,找到如果 0-(c+d)
在map中出现过的话,就用count把哈希表中key对应的value也就是出现次数统计出来。
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
hashMap = dict()
# Count the times of a+b appears
for a in nums1:
for b in nums2:
if a+b not in hashMap:
hashMap[a+b] = 1
else:
hashMap[a+b] += 1
count = 0
for c in nums3:
for d in nums4:
if (0 - (c + d)) in hashMap:
count += hashMap[0-(c+d)]
return count
383. Ransom Note
很简单的用哈希表记录,因为是有限英文字母,可以用数组代替字典,依据ASCII表求字母与a
的相对数。
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
hashTable = dict()
for char in ransomNote:
if char not in hashTable:
hashTable[char] = 1
else:
hashTable[char] += 1
for char in magazine:
if char in hashTable:
hashTable[char] -= 1
if hashTable[char] == 0:
del hashTable[char]
if hashTable == {}:
return True
else:
return False
15. 3Sum
双指针法,先将数组排序,指针i
遍历数组,同时定一个指针left
定义在i+1
的位置上,定义指针right
在数组结尾的位置上。根据结果放缩left
和right
因为数组已经是有序,且target为0,所以若nums[i] > 0
,就可以提前终止;
避免nums[i]
重复:
if i > 0 and nums[i] == nums[i-1]: continue
而不是:
if nums[i] == nums[i+1]: continue
-1,-1,2 这种情况会被忽略
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res = []
for i in range(len(nums)):
# if the first element is > 0, it's impossible to form triplets
if nums[i] > 0:
break
# skip duplicate a
if i > 0 and nums[i] == nums[i-1]:
continue
left = i + 1
right = len(nums) - 1
while left < right:
if nums[i] + nums[left] + nums[right] > 0:
right -= 1
elif nums[i] + nums[left] + nums[right] < 0:
left += 1
else:
res.append([nums[i], nums[left], nums[right]])
# skip duplicate b and c
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 res
18. 4Sum
4Sum 和 3Sum 方法一样,区别是多了一层循环,剪枝和去重有细微差别。
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
res = []
for i in range(len(nums)):
# pruning
if nums[i] > 0 and nums[i] >= target:
break
# remove duplicate nums[i]
if i > 0 and nums[i] == nums[i-1]:
continue
for j in range(i+1, len(nums)):
# second level pruning
if nums[i] + nums[j] > 0 and nums[i] + nums[j] >= target:
break
# remove duplicate nums[j]
if j > i+1 and nums[j] == nums[j-1]:
continue
left = j + 1
right = len(nums) - 1
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:
res.append([nums[i], nums[j], nums[left], nums[right]])
# remove duplicate nums[left] and 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 res