recur
BlogHash Map

Two Sum is not an easy problem

RC
Recur TeamJun 27, 2026 · 3 min read

Two Sum is the first problem everyone solves and the last problem anyone can actually defend. The single-pass hash map answer takes thirty seconds to recite:

def two_sum(nums, target):
    seen = {}
    for i, n in enumerate(nums):
        c = target - n
        if c in seen:
            return [seen[c], i]
        seen[n] = i
    return []

“O(n) time, O(n) space.” Correct — and also the exact point where a good interviewer starts digging, because that O(n) is hiding a word you didn’t say: amortized.

What “amortized O(1)” commits you to

A hash map lookup is O(1) on average, assuming a hash function that spreads keys uniformly across buckets. Say the bolded part out loud. If every key lands in the same bucket — an adversarial input, or a genuinely bad hash function — each lookup degrades to a linear scan of that bucket. The single pass becomes O(n) lookups × O(n) per lookup: O(n²) worst case.

This is not pedantry. It’s the difference between knowing the answer and knowing the data structure:

The follow-up that separates candidates

“The array is read-only and you can’t allocate extra memory.” Now the hash map is off the table. Sorting in place is off the table too — the array is read-only, and you need original indices anyway. What’s left is the O(n²) brute force… unless the array is already sorted, which is exactly why Two Sum II exists as a separate problem: two pointers, O(n) time, O(1) space, no map at all.

The lesson worth retaining: the hash map buys speed with memory and with an assumption about your hash function. Being able to name that assumption — and price out the alternatives when it’s taken away — is what “knowing Two Sum” actually means.

Coach’s note · Next review, skip straight to the worst case: state what breaks the O(1) lookup and what you’d reach for if the interviewer bans the map. The code is the easy 20%.

All posts