Back to Python & Coding

PYTHON & CODING · QUESTION 22

How do you find two numbers that add up to a target?

On this page
Intermediate 5 min read
Interview-ready answerThe concise version to remember

Scan the numbers once while storing values already seen and their indices in a dictionary. For each value, compute the complement needed to reach the target and check whether it is in the dictionary. If so, return the earlier and current indices; otherwise store the current value. This takes O(n) expected time and O(n) extra space, assuming dictionary operations are expected O(1).

LET'S MAKE IT SIMPLE

First, the idea in plain English

A slow approach checks every possible pair, which repeats work as the list grows. Instead, while looking at a number, ask what other number would complete the target and whether you have already seen it. A dictionary makes that lookup fast on average. You store indices so the answer can refer to the original positions, and check before adding the current value so one element is not used twice.

A USEFUL COMPARISON

Picture it this way

Imagine looking for two price tags that total a budget while walking through a store. For each price, you calculate the amount still needed and check a list of prices already passed. The dictionary is that quick lookup list. The analogy explains the complement idea; a program must also handle repeated values and define what to return when no pair exists.

FOLLOW THE JOURNEY

Remember seen values to avoid checking every pair

Trace the complement lookup that reduces pair search from quadratic to linear expected time.

Remember seen values to avoid checking every pairTrace the complement lookup that reduces pair search from quadratic to linear expected time.Algorithm walkthrough
01Read valueCurrent value and index
02Find complementTarget minus current value
03Check seen mapWas complement stored earlier?
04Return or storeReturn pair, otherwise save value and index

Checking before storing prevents the current array position from pairing with itself. A dictionary assignment can overwrite duplicate values, so consider the contract if all pairs are required.

The algorithm scans values, calculates target minus current value, checks a dictionary of previous values, and either returns both indices or stores the current value.

How to read this visual
Checking before storing prevents the current array position from pairing with itself. A dictionary assignment can overwrite duplicate values, so consider the contract if all pairs are required.

UNDER THE HOOD

How it works, step by step

01

Clarify the result

Confirm whether the caller wants indices or values and what to do if no pair exists.

Why it matters: The contract determines edge-case behavior.

02

Compute the complement

For each number x, calculate target - x.

Why it matters: Any matching earlier number must equal that complement.

03

Look up before storing

Check the dictionary for the complement, then store the current value and index if absent.

Why it matters: This avoids pairing an element with itself.

04

State complexity

The scan is O(n) expected time and the dictionary can hold O(n) entries.

Why it matters: This explains the time-space trade-off against checking every pair.

OUTSIDE THE TEXTBOOK

A practical example

For values [4, 7, 1, 9] and target 8, the algorithm first stores 4. At 7, it needs 1, which has not appeared, so it stores 7. At 1, it needs 7, finds the earlier index, and returns the positions of 7 and 1.

GO A LITTLE DEEPER

Technical details that matter

  • A brute-force solution checks all pairs in O(n²) time and O(1) extra space; the dictionary trades memory for expected linear time.
  • If the input is sorted and only values are required, two pointers can use O(1) extra space after sorting, though sorting costs O(n log n) and changes index handling.
  • For duplicate values, checking before insertion allows a pair such as target 6 from [3, 3].
  • Python dictionaries use hashing; O(1) lookup is expected, not a strict worst-case guarantee for every possible key distribution.
Python example
def two_sum(numbers: list[int], target: int) -> tuple[int, int] | None:
    seen: dict[int, int] = {}

    for index, value in enumerate(numbers):
        complement = target - value
        if complement in seen:
            return seen[complement], index
        seen[value] = index

    return None

The function returns the first matching pair of indices, or None when no pair exists. Looking up the complement before inserting the current value prevents reusing the same element.

MAKE A GOOD CHOICE

When is this useful?

  • Finding pairs that meet a target in a single-pass data stream.
  • Recognizing when a hash map can replace repeated nested-loop searches.
  • Practicing how to explain a brute-force baseline and a time-space optimization.
Consider the alternative

If only values are needed and the list can be sorted, a two-pointer approach may reduce auxiliary space. If all matching pairs are required, define duplicate and output-size behavior before choosing the algorithm.

WATCH OUT FOR

Common misunderstandings

  • Returning values when the problem specifically asks for indices.
  • Adding the current value before checking and accidentally using one element twice.
  • Claiming worst-case O(1) hash lookup without qualification.

REAL-WORLD TRADE-OFFS

Limitations and failure cases

  • The dictionary requires O(n) additional memory.
  • The first pair found may not be the only pair; output requirements can change the solution.
  • If input values are not hashable or arrive under a different constraint, the approach must change.

WHAT TO REMEMBER

Key takeaways

  1. 1Use target minus current value to find the required complement.
  2. 2Store previously seen values and their indices in a dictionary.
  3. 3Check before storing to avoid reusing one array position.
  4. 4Explain expected O(n) time and O(n) space.

PRACTICE THE FOLLOW-UP

What might an interviewer ask next?

Why check the dictionary before inserting the current value?

It prevents the current element from matching itself, such as using a single 4 twice to reach 8.

What if the array is sorted?

Two pointers can scan inward with constant extra space when values are required. If original indices are required, preserve their positions through sorting.

How would you return all pairs?

The contract must define whether pairs are distinct by value or by index. Track frequencies or indices and ensure duplicates do not create repeated or invalid results.

SAY IT OUT LOUD

How to explain this in an interview

“I would use a dictionary from previously seen values to their indices. For each number, I calculate the complement, check whether it is already present, and return the two indices if it is. Otherwise, I store the current value and continue. Checking before insertion prevents using one element twice. The expected time is O(n), with O(n) extra space.”

Continue your learning path

Connect this question to the roadmap topic it supports.

Open roadmap topic