LeetCode Two Sum Has Five Solutions. Here's What Each One Teaches.

- Two Sum brute force (O(n²)) is the right starting point in any interview: name its cost, then improve it.
- Sorting unlocks binary search: once data is sorted, O(log n) lookup is always on the table.
- Two pointers work on sorted arrays because sorted order gives you a direction: too small moves the left pointer right, too big moves the right pointer left.
- Hash map (two-pass) is the classic trade-space-for-time move: O(n) extra space eliminates the inner loop entirely.
- One-pass hash map exploits a look-behind structure: the complement either appeared earlier (already in the map) or will appear later (you'll catch it then).
- Pattern recognition beats memorization: if you can't explain why two pointers and binary search have identical complexity on Two Sum, 3Sum will feel like a new problem.
Stop. Before you read further, write down every way you can solve Two Sum. You have thirty seconds.
Most people get one. A few get two. Three means you're already beating the majority of people grinding LeetCode right now. Zero means you've been hitting "submit" and hoping the stars align.
Two Sum is LeetCode problem 1 for a reason. It's not a "warmup" (it's a trap disguised as a warmup). Each of its five solutions is a different mental move that shows up over and over in harder problems. Every one you don't know is a pattern you'll blank on when you actually need it.
The LeetCode Two Sum Problem
Given nums and a target, return indices of two numbers that sum to target.
nums = [2, 7, 11, 15], target = 9 → [0, 1]
Exactly one solution is guaranteed. Indices must be distinct.
How many did you get? Here's the full set.
Solution 1: Just Check Everything (Brute Force)
Check every pair. Enumerate all possibilities. Accept the O(n²) shame.
def two_sum(nums: list[int], target: int) -> list[int]: for i in range(len(nums)): for j in range(i + 1, len(nums)): if nums[i] + nums[j] == target: return [i, j]
O(n²) time, O(1) space.
This teaches you to start with enumeration before you optimize, and to name its cost explicitly. Interviewers want to see the brute force first. It anchors the conversation and proves you understand the problem before trying to be clever. Jumping straight to the hash map without acknowledging the naive approach is, counterintuitively, a red flag.
Pattern transfer: exhaustive enumeration shows up in backtracking, permutation generation, and string search problems. It's always the starting line.
Solution 2: Sort, Then Binary Search
Sort a copy that preserves original indices. For each element, binary-search the rest for its complement.
def two_sum(nums: list[int], target: int) -> list[int]: indexed = sorted(enumerate(nums), key=lambda x: x[1]) values = [v for _, v in indexed] for i, (original_i, num) in enumerate(indexed): complement = target - num lo, hi = i + 1, len(values) - 1 while lo <= hi: mid = (lo + hi) // 2 if values[mid] == complement: return [original_i, indexed[mid][0]] elif values[mid] < complement: lo = mid + 1 else: hi = mid - 1
O(n log n) time, O(n) space.
Sorting transforms an unsearchable array into a structure you can query in O(log n). That transformation is the entire lesson. Once data is sorted, binary search is always on the table. The cost of sorting buys you every future query for free.
Pattern transfer: search in sorted rotated arrays, finding ranges, anything where "find a value satisfying condition X" is the subproblem.
Solution 3: Sort, Then Two Pointers
Same sorted copy, totally different mechanism. Converging pointers eliminate half the remaining search space per step.
def two_sum(nums: list[int], target: int) -> list[int]: indexed = sorted(enumerate(nums), key=lambda x: x[1]) left, right = 0, len(indexed) - 1 while left < right: total = indexed[left][1] + indexed[right][1] if total == target: return [indexed[left][0], indexed[right][0]] elif total < target: left += 1 else: right -= 1
O(n log n) time, O(n) space. Same asymptotic complexity as solution 2, totally different structure.
Two pointers work because sorted order gives you a direction: too small means move left right, too big means move right left. Without sorted order there's no principled way to decide which pointer to move. You'd just be guessing, which is brute force in a costume.
Pattern transfer: 3Sum, 4Sum, Container With Most Water, trapping rainwater. See the full two pointer breakdown.
Solution 4: Hash Map (Two-Pass)
Build the full lookup table first, then scan for complements.
def two_sum(nums: list[int], target: int) -> list[int]: seen = {num: i for i, num in enumerate(nums)} for i, num in enumerate(nums): complement = target - num if complement in seen and seen[complement] != i: return [i, seen[complement]]
O(n) time, O(n) space.
This is the "trade space for time" move in its purest form. You spend O(n) extra memory so every complement check costs O(1) instead of O(n). Quadratic becomes linear. The hash map is basically you betting that RAM is cheap enough to not care about, and in 2026 that bet almost always pays off.
Pattern transfer: group anagrams, subarray sum equals k, two-sum variants on strings.
Solution 5: Hash Map (One-Pass)
Walk the array once. Check if the complement was already seen, then record the current element. No second loop.
def two_sum(nums: list[int], target: int) -> list[int]: seen = {} for i, num in enumerate(nums): complement = target - num if complement in seen: return [seen[complement], i] seen[num] = i
O(n) time, O(n) space. Same complexity as solution 4, but one pass.
You don't need the full map built upfront, because you're looking behind you, not ahead. If the complement appeared earlier, it's in seen. If it appears later, you'll catch it when you get there. The map grows lazily and it still works. This trips people up until it clicks, and then it clicks everywhere.

When you've memorized five Two Sum solutions but your interviewer asks for a hash map explanation and the word is just... gone.
Pattern transfer: this look-behind-while-walking structure is everywhere. Monotonic stacks, sliding window problems, cycle detection. The question "have I seen the thing that would complete my pair?" generalizes to dozens of problems.
Pattern Recognition, Not Memorization
Five solutions, one problem. Each represents a distinct mental move: enumerate first, sort to unlock search, sort to enable direction, trade space for time, look behind while walking.
Two of these solutions have identical time and space complexity (solutions 2 and 3). The point was never "pick the fastest one." It was understanding that the same sorted array supports two fundamentally different query strategies. If that nuance isn't obvious to you right now, 3Sum will feel like a completely new problem when you see it. It isn't.
The gap between candidates who get offers and those who don't is usually pattern recognition, not pattern memorization. You can have solution 5 memorized cold and still fail if you can't explain why solution 3 works but won't work on an unsorted array.
Grinding problems in silence doesn't build this skill. You need to explain the move out loud, under pressure, to someone who'll ask "why not the other approach?" That's exactly what SpaceComplexity is built to train.