Three approaches: nested loops → two pointers → hash map. Learn all three!
Problem Statement
An integer array nums and an integer target. Return the indices of the two numbers that add up to target.
Input: nums = [2, 7, 11, 15], target = 9
Output: [0, 1] → because nums[0] + nums[1] = 2 + 7 = 9
Think of It Like This 🧠
Imagine you're looking at a price list and you have ₹9 to spend on exactly 2 items. You want to find which 2 items cost exactly ₹9 together.
Array: [2, 7, 11, 15] | Target: 9
2 + 7 = 9 ✅ → Answer: [0, 1]
Approach 1 — Brute Force (Nested Loops)
The simplest idea: try every possible pair of numbers. Pick one, then scan all the rest to see if any of them completes the target.
🐌 Brute Force
Two nested loops checking every pair
🔵 Two Pointers
Sort array, shrink from both ends
⚡ Hash Map
One pass with a hash map storing complements
How Brute Force Works
For every element at index i, scan all elements at index j where j > i. If nums[i] + nums[j] == target, return [i, j].
🔍 Dry Run — Brute Force
Input: nums = [2, 7, 11, 15], target = 9
| i | j | nums[i] | nums[j] | Sum | == 9? |
|---|---|---|---|---|---|
| 0 | 1 | 2 | 7 | 9 | ✅ Return [0,1] |
Lucky! Found on first try. But with [15, 11, 7, 2], it would check all pairs before finding the answer — O(n²) in the worst case.
Approach 2 — Hash Map (Optimal) ⚡
Instead of looking forward for a match, we ask: "Have I already seen the number I need?"
For each element nums[i], we calculate complement = target - nums[i]. If that complement is already in our hash map, we found the answer!
Input: [2, 7, 11, 15], target = 9
Return [map.get(2), 1] = [0, 1] ✅
🔍 Dry Run — Hash Map Approach
Input: nums = [2, 7, 11, 15], target = 9
| i | nums[i] | complement | In Map? | Map after step |
|---|---|---|---|---|
| 0 | 2 | 9-2=7 | ❌ No | {2:0} |
| 1 | 7 | 9-7=2 | ✅ Yes (idx 0) | Return [0, 1] |
Approach 3 — Two Pointers (Sort + Squeeze)
Sort a copy of the array (preserving original indices), then place one pointer at the left end and one at the right end. Squeeze them inward based on the sum.
Example: nums = [2, 7, 11, 15], target = 9 → sort with indices tracked
sum = 2 + 15 = 17 → 17 > 9, too big → move RIGHT left
sum = 2 + 11 = 13 → 13 > 9, still too big → move RIGHT left
sum = 2 + 7 = 9 → 9 == 9 ✅ → return original indices [0, 1]
The Three Rules
| sum vs target | Action | Reason |
|---|---|---|
| sum == target | Return the pair ✅ | Found it! |
| sum > target | right-- (move right left) | Need a smaller number on the right |
| sum < target | left++ (move left right) | Need a bigger number on the left |
🔍 Dry Run — Two Pointers
Input: nums = [3, 2, 4], target = 6
After sorting with indices: [(2,idx1), (3,idx0), (4,idx2)]
| left | right | sorted[L] | sorted[R] | sum | Action |
|---|---|---|---|---|---|
| 0 | 2 | 2 (orig:1) | 4 (orig:2) | 6 | ✅ Return [1, 2] |
Input: nums = [2, 7, 11, 15], target = 9
After sorting with indices: [(2,idx0), (7,idx1), (11,idx2), (15,idx3)]
| left | right | sorted[L] | sorted[R] | sum | Action |
|---|---|---|---|---|---|
| 0 | 3 | 2 (orig:0) | 15 (orig:3) | 17 | sum > 9 → right-- |
| 0 | 2 | 2 (orig:0) | 11 (orig:2) | 13 | sum > 9 → right-- |
| 0 | 1 | 2 (orig:0) | 7 (orig:1) | 9 | ✅ Return [0, 1] |
Time & Space Complexity
| Approach | Time | Space | Note |
|---|---|---|---|
| Brute Force | O(n²) | O(1) | Nested loops, checks all pairs |
| Two Pointers | O(n log n) | O(n) | Sort dominates; O(n) extra for index tracking |
| Hash Map | O(n) | O(n) | Single pass, map stores up to n elements |