Solution to LeetCode 15 3Sum and LeetCode 18 4Sum.
LeetCode 15
3 Sum (Medium) [link]
HashTable is not the best method here. The idea of using HashTable is to record all num1, and find whether -num2-num3 is in the record. The time complexity is O(n^2). The space complexity is O(n). The most difficult barrier we are facing with is to remove duplicated values since the indices of the three values should not be the same.
Double pointers is a better idea. First sort the list. Then for each i
, move right
and left
pointers in the range of nums[i+1:]
. If nums[i] + nums[left] + nums[right] > 0
, move right
pointer to the left by 1 step. If nums[i] + nums[left] + nums[right] < 0
, move left
pointer to the right by 1 step. This procedure goes until left = right
. Since our target is zero, after sorting the list, any nums[i]>0
would be impossible to form a combination with a sum of zero.
Time complexity O(n^2). Space complexity O(1).
Remember that double pointer method require sorting the list. If the problem requires to return the index, we cannot use double pointers.
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
nums.sort()
for i in range(n):
left = i+1
right = n-1
if nums[i] > 0:
break # impossible to sum to 0
if i > 0 and nums[i] == nums[i-1]:
continue # remove duplicates
while left < right:
SUM = nums[i] + nums[left] + nums[right]
if SUM > 0:
right -= 1
elif SUM < 0:
left += 1
else:
res.append([nums[i], nums[left], nums[right]])
while left != right and nums[right-1] == nums[right]:
right -= 1 # remove duplicates
while left != right and nums[left+1] == nums[left]:
left += 1 # remove duplicates
left += 1
right -= 1
return res
LeetCode 18
4 Sum (Medium) [link]
The same idea as LC 15. We use two nested for loop to determine nums[i]+nums[j]
, and double pointers to determine nums[k] + nums[i] + nums[left] + nums[right] == target
. Instead of breaking if nums[i]>0
, break if nums[i] > target && (nums[i] >=0 || target >= 0)
.
Time complexity O(n^3).
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
res = []
n = len(nums)
nums.sort()
for i in range(n):
if nums[i] > target and (nums[i] >=0 or target >= 0):
break # prune the tree
if i > 0 and nums[i] == nums[i - 1]: continue
for j in range(i+1,n):
if j > i+1 and nums[j] == nums[j - 1]: continue
left = j+1
right = n-1
while left < right:
SUM = nums[i]+nums[j]+nums[left]+nums[right]
if SUM > target:
right -= 1
elif SUM < target:
left += 1
else:
res.append([nums[i], nums[j], nums[left], nums[right]])
while left != right and nums[left+1] == nums[left]:
left += 1
while left != right and nums[right-1] == nums[right]:
right -= 1
left += 1
right -= 1
return res