Three Sum
Find all unique triplets in an array that sum to zero
Given an integer array nums, return all the triplets [nums[a], nums[b], nums[c]] such that a != b, b != c, a != c, and nums[a] + nums[b] + nums[c] == 0. The solution set must not contain duplicate triplets.
R — READ
READ
What makes a valid triplet? What about duplicates?
Three distinct indices, sum to 0. No duplicate triplets in output (e.g., [0,-1,1] and [-1,0,1] are the same).
Do you understand the 'no duplicates' constraint?
Returning all triplets, even duplicates, or misunderstanding the duplicate requirement.
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Note: [-1, 0, 1] is one triplet.
[-1, -1, 2] is another. [1, 0, -1] is the same as [-1, 0, 1].
O — OBSERVE
OBSERVE
How can I extend the Two Sum idea?
Fix one element, then find two others that sum to the negative of that element. Sort the array to avoid duplicates and enable two-pointer approach.
Can you connect this to Two Sum? Do you see why sorting helps?
Trying all triplets (O(n³)) without recognizing the two-pointer pattern.
Example: [-1, 0, 1, 2, -1, -4]
Sorted: [-4, -1, -1, 0, 1, 2]
Fix -4: find two numbers that sum to 4. None exist.
Fix -1 (first): find two numbers that sum to 1 → [0, 1]. Result: [-1, 0, 1]
Fix -1 (second): skip (duplicate) or find again carefully to avoid duplicate results
Fix 0: find two numbers that sum to 0 → [-1, 1]. But wait, we'd recount.
P — PSEUDOCODE
PSEUDOCODE
How do I avoid duplicates while finding triplets?
Sort array. For each element, fix it and use two pointers on the rest. Skip duplicates of the fixed element.
Clear handling of duplicates in pseudocode.
Pseudocode that doesn't explain duplicate-skipping logic.
1. Sort the array
2. For each index i (fixed element):
a. If i > 0 and nums[i] == nums[i-1], skip (duplicate)
b. Use two pointers (left = i+1, right = len-1)
c. While left < right:
• sum = nums[i] + nums[left] + nums[right]
• If sum == 0, add to result, move both pointers
• If sum < 0, move left right (need larger sum)
• If sum > 0, move right left (need smaller sum)
• Skip duplicates at left and right pointers
3. Return result
I — IMPLEMENT
IMPLEMENT
How do I code this without duplicate triplets?
Sort first. Handle duplicate skipping carefully at all three positions.
Correct duplicate-avoidance logic.
Forgetting to skip duplicates, especially at the left/right pointers.
def threeSum(nums):
"""
Find all unique triplets that sum to zero.
Args:
nums: List of integers
Returns:
List of lists, each triplet summing to 0
"""
nums.sort()
result = []
for i in range(len(nums) - 2):
# Skip duplicate fixed elements
if i > 0 and nums[i] == nums[i - 1]:
continue
# If smallest remaining sum is positive, no solution
if nums[i] > 0:
break
# Two pointers on the rest
left, right = i + 1, len(nums) - 1
while left < right:
total = nums[i] + nums[left] + nums[right]
if total == 0:
result.append([nums[i], nums[left], nums[right]])
# Skip duplicates on left
while left < right and nums[left] == nums[left + 1]:
left += 1
# Skip duplicates on right
while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1
elif total < 0:
left += 1
else:
right -= 1
return result
T — TEST
TEST
Does my code work on all cases?
Test: normal case, no triplets, duplicates, all zeros, mixed positive/negative.
Correctness and duplicate handling.
Only testing when triplets exist.
Test 1: [-1,0,1,2,-1,-4] → [[-1,-1,2],[-1,0,1]] ✓
Test 2: [0,0,0,0] → [[0,0,0]] ✓
Test 3: [-2,0,1,1,2] → [[-2,0,2],[-2,1,1]] ✓
Test 4: [1,2,3] → [] (no triplet sums to 0) ✓
Test 5: [-1,-1,-1,2] → [[-1,-1,2]] (-1 + -1 + 2 = 0) ✓
A — ANALYZE
ANALYZE
What's the complexity?
Sorting is O(n log n). For each of n elements, two-pointer scan is O(n). Total: O(n²).
Correct complexity breakdown.
Claiming O(n) or not accounting for sorting vs. loop.
Why: Sorting is O(n log n). The nested loops (fixed element + two pointers) are O(n²). The overall dominant term is O(n²).
Space: Python's sorted() uses Timsort, which requires O(n) auxiliary space. The two-pointer scan itself uses O(1) extra space (just pointers and variables). We don't count output space.
Brute force: Checking all triplets is O(n³). Two-pointer brings it down to O(n²).