Two Sum

Store what you've seen so each element only looks up its complement.

Approach

The brute force checks every pair in O(n²). Instead, walk the array once and keep a hash map of value → index. For each number, check whether its complement (target − num) is already in the map; if so you're done, otherwise record the current number. You trade O(n) memory for a single linear pass.

Time complexity

O(n)

Space complexity

O(n)

Common mistake

Adding a number to the map before checking for its complement — that can match an element with itself. Check first, then insert.

Interactive walkthrough — step through it below, free and without an account

Problem

Given an array of integers and a target value, find two different positions whose values add up to the target. Return the two indices in any order; the input guarantees that exactly one valid pair exists.

Examples

Input: nums = [2, 7, 11, 15], target = 9

Output: [0, 1]

The values 2 and 7 add to 9, and they appear at indices 0 and 1.

Input: nums = [3, 2, 4], target = 6

Output: [1, 2]

The values 2 and 4 add to 6, at indices 1 and 2.

Problem

Problem

Given an array of integers and a target value, find two different positions whose values add up to the target. Return the two indices in any order; the input guarantees that exactly one valid pair exists.

Problem and Goal

Learning goal: Translate Two Sum into a precise search for a pair of distinct indices.

Core idea For each number, there is exactly one value that would complete the target: complement = target - num. The challenge is to find that complement among values already encountered without comparing every possible pair. Because the answer uses two different elements, the current position must never be paired with itself.

Algorithm plan

  • Scan nums from left to right.
  • For the current value num, compute complement = target - num.
  • Search a map from value to its earlier index.
  • If the complement exists, return its stored index and the current index.
  • Otherwise, store num with its index and continue.

Micro-example For nums = [2, 7, 11, 15] and target = 9, start with 2; its complement is 7, which has not appeared. After storing 2, the next value 7 finds that complement immediately.

Pitfalls

  • The result contains indices, not the two values.
  • The two indices must be different.
  • A hash map lookup is expected to take average O(1) time.

Recap

  • Every number determines one required complement.
  • Scan once while remembering earlier values.
  • Return as soon as the complement is found.

Problem and Goal

Turn pairs into lookups

For each `num`, ask whether `target - num` is already in the map.

Store earlier values; each new value performs one focused lookup.

Key Idea: Remember the Past

Learning goal: Understand why a value-to-index hash map removes the need to rescan earlier elements.

Core idea When the scan reaches num, every earlier value is already a possible partner. Instead of asking the current value to compare against all of them, compute the one value that would make the sum equal target. The map acts as memory: it answers whether that exact complement has appeared and where.

Key insight

The current number does not need to search for many partners. It only needs to look up target - num.

Data structure model

Use a hash map with this meaning:

KeyValueMeaning
numindexThe index where this value was first seen

For each array position, the map contains only earlier positions. This ordering naturally prevents using the same array element twice.

Micro-example At index 1, num = 7 and target = 9, so complement = 2. The map contains {2: 0}, so the answer is [0, 1].

Pitfalls

  • The map stores indices, not just a set of values.
  • Do not confuse num with its complement.
  • The map represents the processed prefix, not the whole array.

Recap

  • target - num is the only candidate partner needed.
  • Value-to-index storage makes the lookup direct.
  • A left-to-right scan keeps partners distinct.

Key Idea: Remember the Past

For `num`, compute `target - num` and look for that key.

For 7: `9 - 7 = 2`

Main Approach and Correct Order

Learning goal: Write the one-pass algorithm in the order that preserves correctness.

Core idea The crucial order is check first, insert second. At index i, the map should contain candidates from indices before i, but not nums[i] itself. Checking first preserves that invariant and prevents a value from satisfying its own complement lookup.

Algorithm plan

Code
seen = empty map
for i from 0 to nums.length - 1:
    num = nums[i]
    complement = target - num
    if complement is in seen:
        return [seen[complement], i]
    seen[num] = i

The map lookup and insertion are average O(1), so each array element is processed once. Compared with brute force, the tradeoff is additional memory for a large reduction in repeated work.

ApproachWorkExtra spaceMain idea
Brute forceO(n²)O(1)Check every pair
Hash mapO(n)O(n)Look up each complement

Micro-example At i = 0, store 2 only after checking for 7. At i = 1, check for 2 before storing 7; the map returns index 0.

Pitfalls

  • Inserting before checking can create a self-match, especially when target = 2 * num.
  • Returning values instead of indices violates the required output.
  • Continuing after a match is unnecessary because the answer is unique.

Recap

  • Check the complement first.
  • Insert the current value only when no match exists.
  • One pass plus a hash map gives O(n) average time.

Main Approach and Correct Order

ApproachWork per elementTotal timeExtra space
Brute forceScan many partnersO(n²)O(1)
Hash mapOne complement lookupO(n)O(n)

Walkthrough: One Example End to End

Learning goal: Trace the map, complement, and answer on one concrete input.

Core idea We will process nums = [2, 7, 11, 15] with target = 9. At every position, the map contains exactly the values from earlier positions. The first successful lookup ends the algorithm, so the remaining values never need to be examined.

Algorithm plan

  • Start with an empty map.
  • At index 0, inspect 2; its complement is 7.
  • Since 7 is absent, record 2 → 0.
  • At index 1, inspect 7; its complement is 2.
  • Since 2 is present at index 0, return [0, 1].

Micro-example Before index 0: seen = {}. After recording index 0: seen = {2: 0}. At index 1, the lookup for 2 succeeds, producing the pair of indices [0, 1].

Pitfalls

  • Do not search for target + num; the equation is num + complement = target.
  • Do not add 7 before checking for 2.
  • Once a match appears, do not process later values as if the answer were unknown.

Recap

  • The map grows only after an unsuccessful lookup.
  • The successful lookup at index 1 points back to index 0.
  • The trace widget shows the invariant after every action.

Walkthrough: One Example End to End

Animate the hash map state and complement lookup for the canonical example.

Variable trace
1 / 8
Start with no values remembered.
VariableValue
i0
numnull
complementnull
seen{}
answernull

Action: initialize

seen contains exactly the values from earlier indices.
1 / 8

Pitfalls and Edge Cases

Learning goal: Recognize the ordering mistake and test the algorithm against tricky inputs.

Core idea A hash map solution is short, but its correctness depends on what the map means at the moment of lookup. Before checking, it must contain only earlier elements. If the current value is inserted first, the algorithm can incorrectly use the same index twice when the target is twice that value.

Common pitfall

Adding a number before checking its complement can match an element with itself. Always check first, then insert.

Algorithm plan

  • Read num and compute complement.
  • Check complement in seen.
  • Return immediately on a hit.
  • Insert num only after a miss.

Micro-example For nums = [3] and target = 6, inserting 3 first would make 3 appear to complement itself. The constraints require two indices, so check-before-insert avoids this invalid match. For [3, 3], the first 3 is stored, and the second 3 correctly finds it.

Pitfalls

  • Duplicate values are valid when they occur at different indices.
  • Negative numbers work because subtraction still computes the complement correctly.
  • Never assume the complement is at a later index; the map only needs earlier values.

Recap

  • Map ordering is a correctness invariant, not just an implementation detail.
  • Check before insertion prevents self-matches.
  • Duplicate and negative values need no special branch.

Pitfalls and Edge Cases

At each index, what should the algorithm do first?

Complexity and Wrap-Up

Learning goal: Explain the performance tradeoff and recognize the reusable hashing pattern.

Core idea The algorithm makes one pass through the array. Each iteration performs an average constant-time hash lookup and, when needed, an average constant-time insertion. The map can hold up to n values, so the method uses linear extra memory to avoid the quadratic pair enumeration of brute force.

Algorithm plan

  • Use a value-to-index hash map.
  • Perform one complement lookup per element.
  • Stop at the first match.
  • Account for the map in the space complexity.

Micro-example For four numbers, brute force may inspect several pairs. The hash-map method inspects index 0, stores it, then finds the answer at index 1 without touching indices 2 and 3.

ResourceCostReason
TimeO(n) averageOne lookup per array element
SpaceO(n)The map stores earlier values

Pitfalls

  • Hash-table operations are average O(1), assuming a suitable hash implementation.
  • The space bound is not O(1) because the map grows with the input.
  • Returning early improves actual work but does not change the worst-case bound.

Recap

  • Store what you have seen so each element looks up its complement.
  • Check first, then insert.
  • Final complexity: O(n) average time and O(n) extra space.

Complexity and Wrap-Up

Show the linear-time, linear-space tradeoff against brute force.

Complexity analysis
Time
O(n)
Space
O(n)
Where the time goes
  • Scan the array onceEach index is processed at most once.dominantO(n)
  • Complement lookupAverage hash-map lookup per iteration.O(1)
  • Map insertionAverage insertion after a miss.O(1)
  • Stored valuesThe map may contain nearly every element.dominantO(n)
How it grows
input size n →opsO(n²)O(n log n)O(n)O(log n)O(1)
Roughly what that costs
n101001,00010,000
O(n)101001K10K

Trading O(n) memory for one linear pass avoids brute force’s O(n²) pair checks.

Now try it on your own problem

Paste any LeetCode problem — or one of your own — and codebrew builds a walkthrough like this one for it.

Build a lesson from any problem

Related problems