3Sum
Question
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]]
such that i != j
, i != k
, and j != k
, and nums[i] + nums[j] + nums[k] == 0
.
Notice that the solution set must not contain duplicate triplets.
Example:
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.
Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.
Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.
Solution
For this question, we need to reduce into TwoSum (Two Pointers way)
So far we can figure out that the best possible complexity would be $O(n^2)$.
So if we can get 1 number as a pivot. We can have the other 2 numbers implemented as TwoSum (Two Pointers way).
This works out because given in the question that we need to avoid duplication. Which means the array needs to be sorted so that if we have already traversed 1 element, we will skip if we see that element again (this concept is the same as Subset > ^d9061d)
Once we sorted it, it gives us benefit for TwoSum (Two Pointers way)
Implementation
class App:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if len(nums) < 3: return []
nums.sort()
result = []
for pivot in range(len(nums)):
if pivot > 0 and nums[pivot] == nums[pivot - 1]:
# Have already done for this pivot
continue
currentNumber = nums[pivot]
left, right = pivot + 1, len(nums) - 1
while (left < right):
currentSum = currentNumber + nums[left] + nums[right]
if (currentSum == 0):
result.append([currentNumber, nums[left], nums[right]])
left += 1
right -= 1
while (left < right) and (nums[left] == nums[left - 1]) and (nums[right] == nums[right + 1]):
# We have already selected these 3 numbers, gotta skip
left += 1
right -= 1
elif currentSum < 0:
# increase left to increase sum
left += 1
else:
# decrease right to decrease sum
right -= 1
return result