Given an array of integers nums and an integer target, return the indices i and j such that nums[i] + nums[j] == target and i != j.
You may assume that every input has exactly one pair of indices i and j that satisfy the condition.
Return the answer with the smaller index first.
Example 1:
Input:
nums = [3,4,5,6], target = 7
Output: [0,1]Explanation: nums[0] + nums[1] == 7, so we return [0, 1].
Example 2:
Input: nums = [4,5,6], target = 10
Output: [0,2]Example 3:
Input: nums = [5,5], target = 10
Output: [0,1]Constraints:
2 <= nums.length <= 1000-10,000,000 <= nums[i] <= 10,000,000-10,000,000 <= target <= 10,000,000
You should aim for a solution with O(n) time and O(n) space, where n is the size of the input array.
A brute force solution would be to check every pair of numbers in the array. This would be an O(n^2) solution. Can you think of a better way? Maybe in terms of mathematical equation?
Given, We need to find indices i and j such that i != j and nums[i] + nums[j] == target. Can you rearrange the equation and try to fix any index to iterate on?
we can iterate through nums with index i. Let difference = target - nums[i] and check if difference exists in the hash map as we iterate through the array, else store the current element in the hashmap with its index and continue. We use a hashmap for O(1) lookups.
Before attempting this problem, you should be comfortable with:
We can check every pair of different elements in the array and return the first pair that sums up to the target. This is the most intuitive approach but it's not the most efficient.
i and j to check every pair of different elements.Input: nums = [2, 7, 11, 15], target = 9
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
0 1 2 3 ← indicesWe check every pair of elements using two nested loops.
Step 1: i = 0, j = 1
i j
↓ ↓
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
Check: nums[0] + nums[1] = 2 + 7 = 9 == target ✓Match found! Return [0, 1]
Visualization of all pairs (if no early match):
┌──────────┬─────────────┬────────────┐
│ Pair │ Calculation │ Result │
├──────────┼─────────────┼────────────┤
│ (0, 1) │ 2 + 7 │ 9 ✓ │ ← Found!
│ (0, 2) │ 2 + 11 │ 13 │
│ (0, 3) │ 2 + 15 │ 17 │
│ (1, 2) │ 7 + 11 │ 18 │
│ (1, 3) │ 7 + 15 │ 22 │
│ (2, 3) │ 11 + 15 │ 26 │
└──────────┴─────────────┴────────────┘Result: [0, 1]
We can sort the array and use two pointers to find the two numbers that sum up to the target. This is more efficient than the brute force approach. This approach is similar to the one used in Two Sum II.
i) and one at the end (j) of the array.i to the right, which will increase the sum.j to the left, which will decrease the sum.Input: nums = [2, 7, 11, 15], target = 9
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
0 1 2 3 ← indicesInitial State: Create array with (value, original_index) pairs
A = [(2, 0), (7, 1), (11, 2), (15, 3)]After Sorting: (already sorted in this case)
i j
↓ ↓
┌───────────┬───────────┬───────────┬───────────┐
│ (2, 0) │ (7, 1) │ (11, 2) │ (15, 3) │
└───────────┴───────────┴───────────┴───────────┘
val=2 val=7 val=11 val=15Step 1: i = 0, j = 3
i j
↓ ↓
┌───────────┬───────────┬───────────┬───────────┐
│ (2, 0) │ (7, 1) │ (11, 2) │ (15, 3) │
└───────────┴───────────┴───────────┴───────────┘
Sum = 2 + 15 = 17 > 9 (target)
Action: Move j left (decrease sum) ←Step 2: i = 0, j = 2
i j
↓ ↓
┌───────────┬───────────┬───────────┬───────────┐
│ (2, 0) │ (7, 1) │ (11, 2) │ (15, 3) │
└───────────┴───────────┴───────────┴───────────┘
Sum = 2 + 11 = 13 > 9 (target)
Action: Move j left (decrease sum) ←Step 3: i = 0, j = 1
i j
↓ ↓
┌───────────┬───────────┬───────────┬───────────┐
│ (2, 0) │ (7, 1) │ (11, 2) │ (15, 3) │
└───────────┴───────────┴───────────┴───────────┘
Sum = 2 + 7 = 9 == target ✓Match found! Original indices are 0 and 1.
Result: [0, 1]
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
A = []
for i, num in enumerate(nums):
A.append([num, i])
A.sort()
i, j = 0, len(nums) - 1
while i < j:
cur = A[i][0] + A[j][0]
if cur == target:
return [min(A[i][1], A[j][1]),
max(A[i][1], A[j][1])]
elif cur < target:
i += 1
else:
j -= 1
return []We can use a hash map to store the value and index of each element in the array. Then, we can iterate through the array and check if the complement of the current element exists in the hash map. The complement must be at a different index, because we can't use the same element twice.
By using a hashmap, we can achieve a time complexity of O(n) because the insertion and lookup time of a hashmap is O(1).
target - nums[i].Input: nums = [2, 7, 11, 15], target = 9
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
0 1 2 3 ← indicesPass 1: Build the HashMap
Iteration 0: indices[2] = 0
Iteration 1: indices[7] = 1
Iteration 2: indices[11] = 2
Iteration 3: indices[15] = 3HashMap after Pass 1:
┌───────┬───────┐
│ Value │ Index │
├───────┼───────┤
│ 2 │ 0 │
│ 7 │ 1 │
│ 11 │ 2 │
│ 15 │ 3 │
└───────┴───────┘Pass 2: Find the complement
Step 1: i = 0, nums[0] = 2
i
↓
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
diff = target - nums[0] = 9 - 2 = 7
Check: Is 7 in HashMap? → YES, at index 1
Check: Is index 1 != index 0? → YES ✓Match found! Return [0, 1]
Result: [0, 1]
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
indices = {} # val -> index
for i, n in enumerate(nums):
indices[n] = i
for i, n in enumerate(nums):
diff = target - n
if diff in indices and indices[diff] != i:
return [i, indices[diff]]
return []We can solve the problem in a single pass by iterating through the array and checking if the complement of the current element exists in the hash map.
If it does, we return the indices of the current element and its complement. If not, we store the current element in the hash map. This guarantees that we will never use the same element twice, but we still check every element in the array.
i and compute the complement of the current element, which is target - nums[i].Input: nums = [2, 7, 11, 15], target = 9
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
0 1 2 3 ← indicesWe iterate through the array once, checking for complement and building the HashMap simultaneously.
Step 1: i = 0, nums[0] = 2
i
↓
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
diff = target - nums[0] = 9 - 2 = 7
HashMap (before):
┌───────┬───────┐
│ Key │ Value │
├───────┼───────┤
│ - │ - │
└───────┴───────┘
Check: Is 7 in HashMap? → NO
Action: Add 2 → 0 to HashMap
HashMap (after):
┌───────┬───────┐
│ Key │ Value │
├───────┼───────┤
│ 2 │ 0 │
└───────┴───────┘Step 2: i = 1, nums[1] = 7
i
↓
┌─────┬─────┬─────┬─────┐
│ 2 │ 7 │ 11 │ 15 │
└─────┴─────┴─────┴─────┘
diff = target - nums[1] = 9 - 7 = 2
HashMap:
┌───────┬───────┐
│ Key │ Value │
├───────┼───────┤
│ 2 │ 0 │
└───────┴───────┘
Check: Is 2 in HashMap? → YES, at index 0 ✓Match found! Return [0, 1]
Visual Summary:
┌──────┬─────────┬──────┬─────────────────┬──────────────────┐
│ Step │ nums[i] │ diff │ HashMap Before │ Action │
├──────┼─────────┼──────┼─────────────────┼──────────────────┤
│ 0 │ 2 │ 7 │ {} │ Add {2: 0} │
│ 1 │ 7 │ 2 │ {2: 0} │ Found! Return ✓ │
└──────┴─────────┴──────┴─────────────────┴──────────────────┘Result: [0, 1]
You cannot use the same element twice to form a pair. When using a hash map, ensure you check that the found index differs from the current index, or use one-pass where you only look at previously seen elements.
# Wrong: might return [i, i] when nums[i] * 2 == target
if diff in indices:
return [i, indices[diff]]
# Correct: ensure different indices
if diff in indices and indices[diff] != i:
return [i, indices[diff]]The problem asks for indices, not the values themselves. A common mistake is returning the two numbers that sum to the target rather than their positions in the array.
When building a hash map with values as keys, duplicate values overwrite earlier indices. In the two-pass approach, this still works because you check indices[diff] != i. In the one-pass approach, you check for the complement before inserting the current element.
The complement should be target - nums[i], not nums[i] - target. Getting this backwards will search for the wrong value.