Input: [-1, 0, 1, 2, -1, -4]. Answer: [-1, -1, 2] and [-1, 0, 1],
each exactly once. Checking every triple is .
Fix one, and it's Two Sum II
Sort first. Then pick a pivot nums[i], and the question "which three
numbers sum to zero?" becomes "which two numbers, to the right of the
pivot, sum to -nums[i]?" That's Two Sum II:
two pointers closing in, one comparison deciding which side to drop.
- Index 0: -4
- Index 1: -1 (i)
- Index 2: -1 (L)
- Index 3: 0
- Index 4: 1
- Index 5: 2 (R)
After a hit, both pointers move in, and the sweep finds 0 + 1 = 1:
the second triplet, [-1, 0, 1]. Running one sweep per pivot
gives overall, and the sort's disappears inside
that.
Where duplicates come from
Now the outer loop moves to the next pivot, index 2. It's another -1.
- Index 0: -4
- Index 1: -1 (done)
- Index 2: -1 (i: skip)
- Index 3: 0
- Index 4: 1
- Index 5: 2
A pivot with the same value as the previous one hunts for the same
target in a subset of the same numbers, so anything it finds is a
repeat. Sorting put equal values side by side, which makes the fix
one line: if nums[i] === nums[i - 1], skip it.
The same thing happens inside the sweep. After recording a hit, if
the next L is the same value as the last one, it pairs with the same
R partner and records the same triplet. So after each hit, step both
pointers past equal neighbours before continuing.
| Rule | Without it |
|---|---|
| Skip a pivot equal to the previous pivot | the whole sweep repeats its triplets |
| After a hit, skip equal neighbours of L and R | the same triplet twice in one sweep |
Start L at i + 1, not 0 | the pivot pairs with itself |
Stop once nums[i] > 0 | wasted sweeps: three positives can't sum to 0 |
Two skips and a sweep
time, extra space beyond the sort and the output. You can't do better than in the worst case anyway: an input full of zeros and pairs can have distinct triplets to return.
The shape generalises. 4Sum fixes two pivots and runs the same sweep inside; 3Sum Closest tracks the best difference instead of matching exactly. Valid Triangle Number flips it around and fixes the largest value, so that one comparison can count a whole range of pairs at once.