Home DSA Three Sum Triplet Problem: 7 Clever Tricks That Always Work
Intermediate 3 min · September 07, 2026

Three Sum Triplet Problem: 7 Clever Tricks That Always Work

Three Sum Triplet solved in O(n^2) with sort + two pointers.

N
Naren Founder & Principal Engineer

20+ years shipping performance-critical code where algorithms decide the bill. Drawn from code that ran under real load.

Follow
Production
production tested
September 22, 2026
last updated
1,799
articles · all by Naren
Before you start⏱ 25 min
  • Two Sum with hash map and two pointers
  • Sorting and in-place array patterns
  • Duplicate-handling in sorted data
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • Three Sum asks for all unique triplets summing to zero (e.g. [-1,0,1,2,-1,-4] gives [[-1,-1,2],[-1,0,1]])
  • Optimal approach: sort O(n log n), then per index run converging two pointers seeking -nums[i] — O(n^2) time, O(1) extra space
  • Key trick: skip duplicates at all three positions (outer i, inner left, inner right) since sorted equals sit adjacent
  • Asked at Amazon, Meta, and Google in most array rounds — the standard k-sum gateway problem
✦ Definition~90s read
What is Three Sum Triplet Problem?

Three Sum is LeetCode 15, a Medium array problem and the gateway to the k-sum family. Given up to 3,000 integers, you return every unique triplet summing to zero. It appears at Amazon, Meta, Google, and Microsoft because it fuses sorting, two pointers, and duplicate elimination into one 30-line test of discipline.

Imagine a row of numbered cards sorted smallest to largest.

The solution sorts once, then treats each index as a frozen anchor for a sorted Two Sum on its tail — converging pointers seeking the negated anchor. Three duplicate-skip sites (outer index, left, right) guarantee uniqueness. Total cost is O(n^2) time with O(1) extra space, worst-case optimal since output alone can reach quadratic size.

Master this skeleton and 4Sum, 3Sum Closest, and all k-sum variants follow the same freeze-and-converge template.

Plain-English First

Imagine a row of numbered cards sorted smallest to largest. Pick one card and note its number — say -1. Now you need two more cards adding to +1. Put one finger on the smallest remaining card and one on the largest. If the trio sums too low, slide the left finger right for a bigger card; too high, slide the right finger left. When it hits exactly zero, write the trio down, then slide both fingers past any identical numbers to avoid repeats. Repeat for each first card. Sorted order plus two sliding fingers checks every possibility without checking every combination.

Three Sum ends more interviews than any other array problem. It looks simple, but it'll punish sloppy thinking.

The brute force is three nested loops. That's O(n^3), dead past n = 500. The hash-set middle ground works but its dedup logic sprawls. You'll tangle yourself in tuple sets and still miss duplicates.

The winning move is sort plus two pointers. Fix one element, then run a converging pair scan on the rest. Duplicates melt away because equal values sit side by side. That's O(n^2) time, O(1) extra space, and the template for 4Sum and every k-sum follow-up. Learn it cold.

Three Numbers Summing to Zero, With No Duplicate Triplets

Given an integer array nums, return all unique triplets [a, b, c] with a + b + c == 0. Order of triplets and order within triplets don't matter, but duplicates are forbidden: [-1,0,1,2,-1,-4] yields exactly [[-1,-1,2],[-1,0,1]]. Note [-1,0,1] appears once even though -1 occurs twice.

Constraints: n up to 3,000 in some versions, values ±10^5. Output size can reach O(n^2) (all zeros), so O(n^2) time is the realistic target. The answer is value triplets, not indices — sorting is allowed.

Walk the example sorted: [-4,-1,-1,0,1,2]. i=0 (-4): need +4 from tail — none. i=1 (-1): tail [-1,0,1,2], left=-1,right=2 sum 0 → record [-1,-1,2], skip dupes. left=0,right=1 sum 0 → record [-1,0,1]. i=2 (dup -1, skip). i=3 (0): need 0 from [1,2] — none. Done: 2 triplets.

📊 Production Insight
Write the expected triplets on the board before touching the keyboard. Candidates who skip this step chase phantom duplicates for 20 minutes.
🎯 Key Takeaway
Unique value triplets summing to zero — trace the sorted example to 2 triplets before coding.

The Triple Loop: 10^9 Checks Plus a Duplicate Problem

Brute force: three nested loops over i < j < k, test the sum, dedup via a set of sorted tuples. Time O(n^3) — at n = 3,000 that's 4.5×10^9 iterations, hours in Python. Space balloons too: the tuple set can hold millions of entries before dedup. At n = 500 (20M iterations) it already exceeds limits.

The hash-set upgrade (O(n^2)): for each i, seek pairs summing to -nums[i] with a seen-set. Better time, but dedup still needs tuple sets and careful index-vs-value bookkeeping. It works yet reads poorly under pressure.

Interview play: name the cubic cost in one breath, note the set variant's dedup pain, and commit to sort + two pointers. That sequencing shows judgment, not just recall.

📊 Production Insight
Say 'cubic is dead past n = 500' out loud. Interviewers log constraint-awareness as a separate positive signal from correctness.
🎯 Key Takeaway
Triple loops cost O(n^3) — at n = 3,000 that's billions of checks; the set variant fixes time but not dedup pain.

Sort First, Then Collapse the Inner Loop to Two Pointers

Sort nums. For each i in range(n-2): skip duplicate i; if nums[i] > 0 break (sorted tail can't reach zero). Set left = i+1, right = n-1, target = -nums[i]. While left < right: s = nums[left] + nums[right]; if s < target: left += 1; if s > target: right -= 1; else record, then skip equal neighbors on both sides and step once more.

Why it works: for fixed i, the tail is sorted, so the converging scan is exactly the sorted Two Sum — pointers move monotonically toward each other, examining each candidate pair once. Skipping adjacent equals after a hit (plus skipping duplicate i) guarantees each distinct value-triplet is emitted once: any duplicate would need the same values at the same positions, which the skips prevent. Per i the scan is O(n); n values of i give O(n^2) time, O(1) extra space beyond output. Sorting adds O(n log n), dominated by the scan.

Early exit nums[i] > 0 is free pruning interviewers love to see. Mention the output-size lower bound too: all-zeros input forces O(n^2) triplets, so O(n^2) is optimal.

📊 Production Insight
Narrate the pointer rule as 'too small, grow left; too big, shrink right.' Saying the rule aloud prevents the reversed-move bug live.
🎯 Key Takeaway
Freeze i, converge the tail on -nums[i], skip dupes at all three levels — O(n^2) optimal by output size.

The Sort-and-Two-Pointer Solution in Full Python

The code above is the complete LeetCode submission. Trace [-1,0,1,2,-1,-4] after sorting to [-4,-1,-1,0,1,2]: i=0 (-4) finds nothing; i=1 (-1) records [-1,-1,2] then [-1,0,1]; i=2 skips as dup; i=3 (0) needs 0 from [1,2], fails. Returns exactly the 2 expected triplets.

Complexity: O(n^2) time, O(1) extra space (output excluded). Sorting is in place; pointers are integers. Handles n = 3,000 within limits.

solution.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution:
    def threeSum(self, nums: list[int]) -> list[list[int]]:
        nums.sort()
        res: list[list[int]] = []
        n = len(nums)
        for i in range(n - 2):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            if nums[i] > 0:
                break
            left, right = i + 1, n - 1
            target = -nums[i]
            while left < right:
                s = nums[left] + nums[right]
                if s < target:
                    left += 1
                elif s > target:
                    right -= 1
                else:
                    res.append([nums[i], nums[left], nums[right]])
                    while left < right and nums[left] == nums[left + 1]:
                        left += 1
                    while left < right and nums[right] == nums[right - 1]:
                        right -= 1
                    left += 1
                    right -= 1
        return res
⚠ The Triple-Skip Rule
Skip duplicates in THREE places: outer i, inner left, inner right. Miss one and repeats return.
📊 Production Insight
After writing, run the all-zeros case [0,0,0,0] mentally: expect [[0,0,0]] once. It exercises every skip branch in four elements.
🎯 Key Takeaway
Sort, freeze, converge, triple-skip — verify on the 6-element example plus all-zeros.

All Zeros, Arrays Under Three Elements, Duplicate Blocks

All zeros [0,0,0,0] must yield [[0,0,0]] exactly once — the skips collapse everything. Fewer than 3 elements returns []. No valid triplet returns []. All-positive sorted input triggers the nums[i] > 0 break instantly. Large duplicate blocks ([-2,-2,...,-2,4,4,...]) stress the skip loops; each while must be bounded by left < right.

Watch for triplet-as-indices bugs: the answer holds values, so appending [i, left, right] fails validation. Also watch integer types in static languages (sums fit in 32-bit here given ±10^5, but mention long for safety). Target-nonzero variants drop the > 0 early break — flag that when generalizing.

📊 Production Insight
The [0,0,0,0] case is the highest-value single test: it passes only when all three skip sites work together.
🎯 Key Takeaway
Test all-zeros, short arrays, no-solution, and all-positive inputs — four cases cover every branch.

Why O(n^2) Cannot Be Beaten on This Problem

Time O(n^2): n outer positions times O(n) inner scans, plus O(n log n) sort absorbed into the quadratic term. Space O(1) besides output: a few integers. Optimality follows from output size — degenerate inputs force Ω(n^2) triplets, so no algorithm can run faster in the worst case.

Whiteboard closer: 'Sort once, then n sorted Two Sums; duplicates die at three skip sites.' Then bridge forward: '4Sum fixes one more index for O(n^3); k-sum is O(n^(k-1)).' That bridge converts a Medium pass into a Hard-ready signal.

📊 Production Insight
Cite the all-zeros lower bound explicitly. Optimality arguments backed by a concrete input beat generic 'can't do better' claims.
🎯 Key Takeaway
Output size can hit Ω(n^2), so the O(n^2) scan is worst-case optimal — sorting never dominates.
● Production incidentPOST-MORTEMseverity: high

The 25-Minute Cubic Loop That Froze an Amazon Loop

Symptom
The triple loop passed the 6-element example but froze on the 1,500-element stress test. The fallback hash-set version then returned 5 triplets instead of 2, with duplicates differing only in index order.
Assumption
The candidate assumed dedup could be bolted on at the end with a set of tuples, and that the O(n^3) triple loop would pass 'because interview inputs are small'. They never asked about constraints.
Root cause
Three nested loops over 1,500 elements meant ~3.4 billion iterations (timeout), and the tuple-set dedup stored every permutation — memory ballooned past 500MB before the timeout killed the run.
Fix
The interviewer pointed at the sorted array and asked what order buys them. The candidate rebuilt as freeze-i plus two pointers with duplicate skips, passing all cases with 6 minutes left — but needed the nudge, so the round graded as weak hire.
Key lesson
  • Sort first, then let sorted order do the dedup work — adjacent equal values make skipping a one-line while loop.
  • After each found triplet, skip duplicates on BOTH sides before continuing; skipping one side still emits repeats.
Production debug guideFour defect shapes and the exact check that exposes each one.4 entries
Symptom · 01
Duplicate triplets in the output
Fix
Add 'if i > 0 and nums[i] == nums[i-1]: continue' at the loop top. After each recorded triplet, add while-loops skipping equal neighbors on both sides, then step once more. Rerun [-1,0,1,2,-1,-4] expecting exactly 2 triplets.
Symptom · 02
Infinite loop or hang on small inputs
Fix
Verify every branch moves a pointer: sum < 0 → left += 1; sum > 0 → right -= 1; equal → record, skip duplicates, then left += 1 and right -= 1. Single-step with left == right adjacent values to confirm termination.
Symptom · 03
Missing valid triplets (e.g. [-1,-1,2] absent)
Fix
Print (i, left, right, nums[i], nums[left], nums[right]) per step on [-1,0,1,2,-1,-4]. If i changes mid-scan, the outer variable leaked into the inner loop — rename inner indices and freeze i for the whole scan.
Symptom · 04
No early exit on all-positive arrays, or triplets hold wrong values
Fix
Insert 'if nums[i] > 0: break' after sorting (for target zero). Confirm the sorted array and that triplets are appended as [nums[i], nums[left], nums[right]] value lists, not index lists.
Three Sum Approaches Compared
ApproachTimeSpaceVerdict
Brute force (three loops)O(n^3)O(1) + outputDead past n = 500
Hash set per i (no sort)O(n^2)O(n)Works, but dedup logic is painful
Sort + two pointersO(n^2)O(1) + outputBest: clean dedup, least memory
Sort + binary search for thirdO(n^2 log n)O(1) + outputCorrect but needlessly slower

Key takeaways

1
Three Sum asks for unique triplets summing to zero; sort + two pointers solves it in O(n^2) time, O(1) extra space.
2
Freeze index i, then converge left/right on the tail seeking -nums[i]
a Two Sum on sorted data.
3
Skip duplicates at all three positions
outer i, inner left, inner right.
4
Break early when nums[i] > 0 since sorted tails can't sum to zero beyond that.
5
The freeze-one-plus-two-pointers skeleton generalizes to 4Sum O(n^3) and k-sum O(n^(k-1)).

Common mistakes to avoid

4 patterns
×

Skipping duplicate elimination and returning repeated triplets

Symptom
[-1,0,1,2,-1,-4] returns [[-1,0,1],[-1,0,1],...] with repeats instead of [[-1,-1,2],[-1,0,1]]. LeetCode's set-comparison rejects it.
Fix
After finding a triplet, advance left past all equal values and retreat right past all equal values before continuing. Also skip duplicate i values at the outer loop start (if i > 0 and nums[i] == nums[i-1]: continue).
×

Modifying values instead of sorting, or sorting and losing originals

Symptom
Triplets contain values not present in the input, or the sort breaks index-based follow-ups like 3Sum Closest. Output fails multiset validation.
Fix
Sort a copy (or sort in place, since LeetCode passes ownership) and use index pointers only. Never mutate element values. Keep the original values intact for output triplets.
×

Moving the fixed index inside the pair scan

Symptom
Missed triplets and index-out-of-range crashes. The outer anchor must stay frozen while left/right converge.
Fix
Treat the pair search as a fresh two-sum on the subarray (i+1..end) with target -nums[i]. The two pointers converge on the sorted tail; the fixed i never moves during the inner scan.
×

Infinite loops from pointers that don't advance, or submitting O(n^3)

Symptom
Editor hangs on [-1,0,1,2,-1,-4], or the cubic triple loop times out past n = 500. Every branch must move a pointer.
Fix
Use while left < right with pointer moves on every branch, and break inner-loop early when nums[i] > 0 (sorted array can't sum to zero beyond that). For brute force, name O(n^3) and pivot — never submit it.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Explain the full algorithm and its complexity.
Q02SENIOR
How do you guarantee no duplicate triplets?
Q03SENIOR
Generalize to 4Sum and k-sum. What's the complexity?
Q01 of 03SENIOR

Explain the full algorithm and its complexity.

ANSWER
Sort O(n log n). For each i, two-pointer scan the tail for pairs summing to -nums[i]: move left right on shortfall, right left on overshoot, record and skip duplicates on hit. Skip duplicate i values. O(n) work per i gives O(n^2) total; pointers use O(1) extra space.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Why is sorting the first step?
02
Can I solve it without sorting?
03
How does 3Sum relate to Two Sum?
04
Can anyone beat O(n^2)?
05
How do I adapt this to a nonzero target or 3Sum Closest?
N
Naren Founder & Principal Engineer

20+ years shipping performance-critical code where algorithms decide the bill. Drawn from code that ran under real load.

Follow
Verified
production tested
September 22, 2026
last updated
1,799
articles · all by Naren
🔥

That's Arrays. Mark it forged?

3 min read · try the examples if you haven't

Previous
Best Time to Buy and Sell Stock
2 / 3 · Arrays
Next
Container With Most Water