Two Sum
The canonical hash map problem: trade space for a lookup, and turn a nested scan into one pass.
- Pattern
- Hash map — store the value, look up the complement
- Difficulty
- Easy
- Time
- O(n)
- Space
- O(n)
Given an array of integers and a target, return the indices of the two numbers that add up to the target. Exactly one solution exists, and you can't use the same element twice. (LC 1)
It's the first problem everyone solves, and it still earns its place in the rotation — because it's the purest form of the most common optimization in interviews: replace an inner loop with a hash map lookup.
The recipe
Say before you type: "I store the value I've seen; I look up the complement."
- Walk the array once.
- For each element, compute
complement = target - nums[i]. - If the complement is already in the map, you're done — return its stored index and the current one.
- Otherwise store the value as the key and the index as the value, and keep walking.
The code
function twoSum(nums: number[], target: number): number[] {
const seen = new Map<number, number>(); // value -> index
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (seen.has(complement)) return [seen.get(complement)!, i];
seen.set(nums[i], i); // store the VALUE as key, index as value
}
return [];
}
Why this shape
The brute force checks every pair: two nested loops, O(n²). The question the optimal solution answers is "have I already seen the number that would complete this pair?" — and "have I seen X?" is exactly what a hash map answers in O(1).
One pass does both jobs at once: each element is simultaneously a candidate answer (does my complement exist yet?) and a future ingredient (record me for later). Checking before inserting also handles the target = 2 × nums[i] case for free — you never match an element against itself.
Complexity
| Cost | Because | |
|---|---|---|
| Time | O(n) | One pass; each map get/set is O(1) average |
| Space | O(n) | The map can end up holding every element |
Traps
- Flipping key and value. The map is
value → index. If you storeindex → value, thehas(complement)lookup silently checks the wrong thing. Say the pre-flight sentence out loud — the flip usually happens on the return line. - Inserting before checking. Insert-first means an element can match itself when
targetis exactly twice its value. - Returning the values instead of the indices the problem asked for.
The pattern this trains
Whenever an interviewer asks "can you do better than O(n²)?", the answer is very often this move: a hash map that turns the inner "find my partner" scan into a lookup. Contains Duplicate (LC 217), Group Anagrams (LC 49), and Top K Frequent (LC 347) are all the same muscle.