Example 1
ready- Input
nums = [ 2, 7, 11, 15 ] target = 9- Expected
[ 0, 1 ]- Why
- 2 + 7 = 9
You're given an array of integers nums and a single integer target.
Exactly one pair of positions in the array adds up to target. Your job is to find
that pair and return the two indices, in any order.
A few ground rules:
2 <= nums.length <= 10_000-1_000_000_000 <= nums[i], target <= 1_000_000_000Hints
What's the most obvious thing that could possibly work? Check every pair. Count how many pair-checks that is for 10,000 numbers before you fall in love with it.
While scanning, you keep asking: "have I already seen the number that would complete this one?" That question — have I seen X — is exactly what a hash map answers in O(1).
For each nums[i], look up target - nums[i] in the map first, then store
nums[i] → i. Storing after looking up is what prevents pairing an element with itself.
Could you do it in one pass even if the array were streaming in and you never saw it again?
Visible cases
nums = [
2,
7,
11,
15
]
target = 9[
0,
1
]nums = [
3,
2,
4
]
target = 6[
1,
2
]nums = [
3,
3
]
target = 6[
0,
1
]Interview signal
Fix the first index i, then scan every later index j asking whether
nums[i] + nums[j] == target. The inner scan starts at i + 1, so no pair is checked
twice and no element pairs with itself.
def two_sum(nums: list[int], target: int) -> list[int]:
n = len(nums)
for i in range(n - 1):
for j in range(i + 1, n):
if nums[i] + nums[j] == target:
return [i, j]
return [] # unreachable: exactly one solution is guaranteedTime O(n²) — about n²/2 pair-checks; at n = 10,000 that's ~50 million, which is why the big hidden tests refuse this one in the slower languages. Space O(1).
The brute force keeps re-answering the same question by re-scanning: "is the partner of
nums[i] somewhere in the array?" Flip the direction: as you walk the array once,
record every value you've passed in a map from value → index. Before recording nums[i],
ask the map whether its partner target - nums[i] was already seen.
def two_sum(nums: list[int], target: int) -> list[int]:
seen: dict[int, int] = {}
for i, x in enumerate(nums):
partner = target - x
if partner in seen:
return [seen[partner], i]
seen[x] = i
return [] # unreachableLook up before you insert: that ordering is the whole correctness argument. It makes
pairing an index with itself impossible, and duplicate values just work — when the second
3 of [3, 3] arrives, the first is already in the map.
Time O(n) — one pass, O(1) expected per lookup. Space O(n) for the map.
That single trade — a map's worth of memory for a linear scan — is the founding move of the whole Arrays & Hashing pattern. You'll spend it again and again.
Ready to run.
3 cases are queued.
Visible testcase
Case 1
Expected
[ 0, 1 ]