array-sum
algorithm
number-pair
unsorted-array
problem-solving

Find 2 numbers in an unsorted array equal to a given sum

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Finding two numbers in an unsorted array that add up to a target is a classic problem because it looks simple but quickly exposes tradeoffs between time, space, and output requirements. The best-known solution is a one-pass hash-table approach, but it is useful to understand why it works and when an alternative is better.

The exact task can vary slightly: return one pair, return the indices, or return all matching pairs. The algorithm choice depends on that requirement.

Brute Force Is Simple but Slow

The direct solution is to test every pair.

python
1def find_pair_bruteforce(nums, target):
2    for i in range(len(nums)):
3        for j in range(i + 1, len(nums)):
4            if nums[i] + nums[j] == target:
5                return nums[i], nums[j]
6    return None
7
8
9print(find_pair_bruteforce([8, 7, 2, 5, 3, 1], 10))

This is easy to understand, but it takes O(n^2) time, which becomes expensive as the input grows.

Use a Hash Set or Dictionary for a One-Pass Solution

For the common version where you only need one valid pair, scan the array once and remember which values you have already seen.

python
1def find_pair(nums, target):
2    seen = set()
3
4    for num in nums:
5        needed = target - num
6        if needed in seen:
7            return needed, num
8        seen.add(num)
9
10    return None
11
12
13print(find_pair([8, 7, 2, 5, 3, 1], 10))
text
(8, 2)

This runs in average O(n) time with O(n) extra space. For most interview and production scenarios, this is the best default answer.

Return Indices Instead of Values

Some versions of the problem require indices rather than the numbers themselves. In that case, store index positions in a dictionary.

python
1def find_pair_indices(nums, target):
2    seen = {}
3
4    for index, num in enumerate(nums):
5        needed = target - num
6        if needed in seen:
7            return seen[needed], index
8        seen[num] = index
9
10    return None
11
12
13print(find_pair_indices([8, 7, 2, 5, 3, 1], 10))

This preserves the same O(n) average running time while giving index information directly.

Sort and Use Two Pointers When Ordering Helps

Another efficient option is sorting first and then moving two pointers toward each other.

python
1def find_pair_sorted(nums, target):
2    nums = sorted(nums)
3    left = 0
4    right = len(nums) - 1
5
6    while left < right:
7        total = nums[left] + nums[right]
8
9        if total == target:
10            return nums[left], nums[right]
11        if total < target:
12            left += 1
13        else:
14            right -= 1
15
16    return None
17
18
19print(find_pair_sorted([8, 7, 2, 5, 3, 1], 10))

This takes O(n log n) time because of sorting and O(n) extra space in Python if you sort a copy. It is useful when:

  • you want all pairs in sorted order
  • hashing is not available or not desirable
  • you are already sorting the data for another reason

The tradeoff is that sorting changes the order, which may matter if you need original indices.

How the Hash-Based Idea Works

The one-pass solution is fast because every time you see a number num, you can compute the only value that would complete the target: target - num. If that complementary value has already appeared, you have found a valid pair immediately.

That insight turns a nested search into a stream of constant-time membership checks. Conceptually, you are asking “did I already see the number that would finish this sum?”

If You Need All Pairs

Returning all pairs is a slightly different problem. A simple one-pair function stops early, but a full solution must keep scanning and handle duplicates carefully so it does not emit the same logical pair multiple times.

For example, with [1, 9, 9, 1] and target 10, you need to decide whether you want value pairs such as (1, 9) once, or index pairs for every valid combination. That requirement changes the implementation significantly.

Common Pitfalls

The most common mistake is forgetting that the two numbers must come from different positions. You cannot use the same element twice unless it appears twice in the array.

Another issue is storing values when the problem actually asks for indices. The hash-table idea still works, but the stored data should be indices instead of just seen values.

People also overlook duplicates. If the input contains repeated numbers, be clear about whether you want the first pair found, all unique value pairs, or all index combinations.

Finally, remember that the sort-and-two-pointer approach is excellent for values but awkward if original positions matter. Once you sort, the original indexing information is gone unless you preserve it explicitly.

Summary

  • The brute-force solution is easy to write but costs O(n^2) time.
  • The standard efficient answer is a one-pass hash-based scan with average O(n) time.
  • Use a dictionary instead of a set when the problem asks for indices.
  • The sort-and-two-pointer approach is a good alternative when order does not matter.
  • Be precise about duplicates and whether you need one pair, all pairs, values, or indices.

Course illustration
Course illustration

All Rights Reserved.