015. 3Sum
At a Glance
- Topic: two-pointers
- Pattern: Two Pointers
- Difficulty: Medium
- Companies: Amazon, Google, Meta, Bloomberg, Adobe
- Frequency: Very High
- LeetCode: 15
Problem (one-liner)
Given an integer array, return all unique triplets [a, b, c] such that a + b + c == 0. Order within triplets and among triplets follows typical LeetCode expectations (sort outer loop and skip duplicates).
Recognition Cues
- "Three numbers sum to zero / target"
- "Find all unique triplets"
- Unsorted array → sort unlocks two-pointer sweep
Diagram
At-a-glance flow (replace with problem-specific Mermaid as you refine this note). camelCase node IDs; no spaces in IDs.
Loading diagram…
Approaches
- Brute force —
O(n³)time /O(1)space — three nested loops + dedupe set. - Better — sort + for each
anchor, two pointers —O(n²)time /O(1)extra beyond output — standard interview solution. - Optimal — same as better for this model —
O(n²)time /O(1)auxiliary if output not counted.
Optimal Solution
Go
import "sort"
func threeSum(nums []int) [][]int {
sort.Ints(nums)
n := len(nums)
out := [][]int{}
for anchor := 0; anchor < n-2; anchor++ {
if anchor > 0 && nums[anchor] == nums[anchor-1] {
continue
}
left, right := anchor+1, n-1
for left < right {
sum := nums[anchor] + nums[left] + nums[right]
if sum == 0 {
out = append(out, []int{nums[anchor], nums[left], nums[right]})
for left < right && nums[left] == nums[left+1] {
left++
}
for left < right && nums[right] == nums[right-1] {
right--
}
left++
right--
} else if sum < 0 {
left++
} else {
right--
}
}
}
return out
}JavaScript
function threeSum(numbers) {
numbers.sort((a, b) => a - b);
const triplets = [];
const length = numbers.length;
for (let anchor = 0; anchor < length - 2; anchor++) {
if (anchor > 0 && numbers[anchor] === numbers[anchor - 1]) {
continue;
}
let left = anchor + 1;
let right = length - 1;
while (left < right) {
const sum = numbers[anchor] + numbers[left] + numbers[right];
if (sum === 0) {
triplets.push([
numbers[anchor],
numbers[left],
numbers[right],
]);
while (left < right && numbers[left] === numbers[left + 1]) {
left++;
}
while (left < right && numbers[right] === numbers[right - 1]) {
right--;
}
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return triplets;
}Walkthrough
Input: nums = [-1,0,1,2,-1,-4] → sorted [-4,-1,-1,0,1,2]
| anchor | nums[anchor] | left/right sweep | triplet |
|---|---|---|---|
| 1 | -1 | -1+0+1=0 | [-1,-1,2] skipped dup logic … |
Invariant: for fixed anchor, sorted two-pointer finds all pairs summing to -nums[anchor] without revisiting duplicate values.
Edge Cases
- All zeros
- No solution
- Many duplicate values
- Large positives only / negatives only
Pitfalls
- Forgetting to skip duplicate
anchorvalues - Advancing
left/rightwithout shrinking duplicates after a hit - Using hash set without careful dedupe (two-pointer after sort is cleaner)
Similar Problems
- 16. 3Sum Closest — track closest sum instead of zero.
- 18. 4Sum — add another nested layer or reduce to two-sum pairs.
- 167. Two Sum II — Input Array Is Sorted — two-pointer pair sum on sorted array.
Variants
- 3Sum closest to target — same skeleton, track best absolute diff.
- Count triplets with sum
< target— two-pointer with counting tweaks.
Mind-Map Tags
#two-pointers #sort #dedupe #triplet #two-sum-extension
Last updated on
Spotted something unclear or wrong on this page?