LC 454, 15, 18 Hash table 2
Second part of hash table.
LC 454. 4Sum II
Logic
The logic is about the same as the “3 sum”, “2 sum” problems. What need to be done is just record the current sum in a dict
, and upon the time the complement to the target, 0, is found in the dict
, we can imncrease the accumulator.
def fourSumCount(
self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]
) -> int:
dict1 = defaultdict(int)
count = 0
for i in nums1:
for j in nums2:
dict1[i + j] += 1
for i in nums3:
for j in nums4:
key = 0 - i - j
count += dict1[key]
return count
LC 15. 3Sum
Naive solution - brute force
Logic
- Literally check every triplets in three
for
loop, which result in a time complexity of O ( n 3 ) O(n^3) O(n3). - We can fix the first number for the second
for
loop and fix the first pair of sum for the thirdfor
loop, which helps a little. - There are more things to add, for example, one could skip some pairs which are seen before. I only added the
tup
set for removing duplicate.
def threeSum(self, nums: List[int]) -> List[List[int]]:
# naive
nums.sort()
ret = []
tup = set()
for i in range(len(nums)-2):
diff = 0 - nums[i]
for j in range(i+1, len(nums)-1):
diff2 = diff - nums[j]
for k in range(j+1, len(nums)):
if diff2 == nums[k]:
temp = tuple((nums[i], nums[j], nums[k]))
if temp not in tup:
ret.append([nums[i], nums[j],nums[k]])
tup.add(temp)
return ret
Dict
- The source code could be found here: 第15题. 三数之和.
Duo Ptrs
Logic
To use duo-pointers to solve this problem, one could think of each pairs as a prefix sum, then linearly search for the complement of the target.
def threeSum2(self, nums: List[int]) -> List[List[int]]:
nums.sort()
ret = set()
for i in range(len(nums)):
if i > 0 and nums[i] == nums[i - 1]:
continue
j = i + 1
k = len(nums) - 1
while j < k:
s = nums[j] + nums[k]
if s + nums[i] < 0:
j += 1
elif s + nums[i] > 0:
k -= 1
else:
ret.add((nums[i], nums[j], nums[k]))
j += 1
k -= 1
while j < k and nums[j] == nums[j - 1]:
j += 1
while j < k and nums[k] == nums[k + 1]:
k -= 1
return [list(i) for i in ret]
LC 18 4Sum
Dict method
Logic
- Using the
dict
, we could save the sum so far for each pair of nums, then check for other pairs if their complement are already in the dict. - To reduce some of the duplicates, we limit the maximum occurance of an item to a maximum of 4, because we are doing a “4Sum”, and seeing 5 same “2” won’t change the result as 4 “2”.
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
dict1 = defaultdict(list)
visited = set()
ct = Counter(nums)
for key in ct:
ct[key] = min(4, ct[key])
nums = sorted(ct.elements())
for i in range(len(nums) - 1):
for j in range(i + 1, len(nums)):
key = nums[i] + nums[j]
dict1[key].append([i, j])
if target - key in dict1:
for pair in dict1[target - key]:
x, y = pair
keyLst = [nums[i], nums[j], nums[x], nums[y]]
keyLst = tuple(keyLst)
if i not in pair and j not in pair and keyLst not in visited:
visited.add(keyLst)
return list(visited)
Duo ptrs
Logic
- Like other sum problems, we could fix the sum of the first two numbers, then using two pointers to find the last two numbers which reduce the brute force runtime from O ( n 4 ) O(n^4) O(n4) to O ( n 3 ) O(n^3) O(n3).
def fourSum2(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
ret = []
for i in range(len(nums) - 1):
if nums[i] > target and nums[i] >= 0:
break
if i > 0 and nums[i - 1] == nums[i]:
continue
for j in range(i + 1, len(nums)):
fixed_sum = nums[i] + nums[j]
if fixed_sum > target and fixed_sum >= 0:
break
if j > i + 1 and nums[j] == nums[j - 1]:
continue
left = j + 1
right = len(nums) - 1
while left < right:
if fixed_sum + nums[left] + nums[right] > target:
right -= 1
elif fixed_sum + nums[left] + nums[right] < target:
left += 1
else:
ret.append([nums[i], nums[j], nums[left], nums[right]])
right -= 1
left += 1
return ret
Summary:
-
When dealing with the “3Sum”, “4Sum” problems, we may consider using duo-pointers rather than the hash table to reduce a bit of the runtime.
-
Meanwhile, we need to figure out when it is best to reduce the duplicates and skip some condition that we have already faced.
-
Total time: About 3 hrs.