How do you solve 3Sum, and why do you sort the input first?
Sort the array, then fix one element at a time and use two pointers to find a pair that completes the triple to zero. The sort is what makes the two pointers possible: once the values are ordered, a comparison between the two pointer values tells you which one to move, and you can rule out entire ranges.
def three_sum(nums):
values = sorted(nums)
triples = []
for i in range(len(values) - 2):
if i > 0 and values[i] == values[i - 1]:
continue
left, right = i + 1, len(values) - 1
while left < right:
total = values[i] + values[left] + values[right]
if total == 0:
triples.append((values[i], values[left], values[right]))
left += 1
right -= 1
elif total < 0:
left += 1
else:
right -= 1
return triples
print(three_sum([-1, 0, 1, 2, -1, -4]))The output is the two triples of minus one, minus one, two and minus one, zero, one. The sort put the array into the order minus four, minus one, minus one, zero, one, two, and the outer loop skipped the second minus one because the first one already produced every triple containing that value.
The two pointer logic is the standard argument. If the running total is negative, the left value is too small, so you need a larger one and the left pointer moves right. If the total is positive, the right value is too large, so the right pointer moves left. Because the array is sorted, neither move can skip a valid triple.
The trade-off to name is that the sort costs O of n log n time and a copy of the array, and the outer loop then makes the inner scan linear, so the overall bound is O of n squared time with O of n space for the output. That quadratic cost is unavoidable when all triples must be reported, because there can be quadratically many of them. Sorting is worth it here precisely because it turns an unsolvable quadratic search into a quadratic search that never explores the same pair twice.