|
| 1 | +# Understanding the Two Pointers Concept |
| 2 | + |
| 3 | +Think of the Two Pointers technique like two people searching for a specific book on a long bookshelf. Instead of one person starting at the left and checking every single combination of books (which takes forever), one person starts at the far left, and the other starts at the far right. They look at the books they are holding, communicate, and take steps toward each other until they find exactly what they are looking for. |
| 4 | + |
| 5 | +Instead of an O(N^2) double-loop comparing every single pair, we use two pointers to scan the array simultaneously, completing the search in just O(N) time. |
| 6 | + |
| 7 | +There are two primary types: |
| 8 | +1. **Opposite Ends (Collision)** (Pointers start at opposite ends and move toward the center). |
| 9 | +2. **Same Direction (Trailing)** (Pointers start at the same end but move at different speeds or intervals). |
| 10 | + |
| 11 | +## Type 1: Opposite Ends (Collision) |
| 12 | +In this type, the array must usually be **sorted**. We place a `Left` pointer at index 0 and a `Right` pointer at the last index. Because the array is sorted, we know exactly which pointer to move based on our current calculation. |
| 13 | + |
| 14 | +- If the current sum is **too small**, we need a bigger number, so we move the `Left` pointer to the right. |
| 15 | +- If the current sum is **too big**, we need a smaller number, so we move the `Right` pointer to the left. |
| 16 | + |
| 17 | +### The Process Step-by-Step |
| 18 | +**Goal:** Find a pair of numbers that add up to the Target Sum of `8` in the sorted data: `[1, 2, 3, 4, 6]`. |
| 19 | + |
| 20 | +```plaintext |
| 21 | +Data: 1 2 3 4 6 |
| 22 | + ^ ^ |
| 23 | + Left Right |
| 24 | + --------------------------------- |
| 25 | +Step 1: [1] 2 3 4 [6] (1+6 = 7. 7 < 8. Too small! Move Left ->) |
| 26 | +Step 2: 1 [2] 3 4 [6] (2+6 = 8. TARGET FOUND! Stop.) |
| 27 | +``` |
| 28 | + |
| 29 | +Let's try a slightly longer one with a Target Sum of `10` in `[2, 3, 5, 8, 9, 11]`. |
| 30 | + |
| 31 | +```plaintext |
| 32 | +Data: 2 3 5 8 9 11 |
| 33 | + ---------------------------------- |
| 34 | +Step 1: [2] 3 5 8 9 [11] (2+11 = 13. 13 > 10. Too big! Move <- Right) |
| 35 | +Step 2: [2] 3 5 8 [9] 11 (2+9 = 11. 11 > 10. Too big! Move <- Right) |
| 36 | +Step 3: [2] 3 5 [8] 9 11 (2+8 = 10. TARGET FOUND! Stop.) |
| 37 | +``` |
| 38 | + |
| 39 | +## Type 2: Same Direction (Trailing/Slow & Fast) |
| 40 | +Here, both pointers start at the beginning (index 0). One pointer is the "explorer" (Fast), and the other is the "marker" (Slow). This is extremely common when you need to process an array in-place, like removing duplicates. |
| 41 | + |
| 42 | +- **Fast Pointer**: Scans the array looking for new/unique elements. |
| 43 | +- **Slow Pointer**: Keeps track of where the next unique element should be placed. |
| 44 | + |
| 45 | +### The Process Step-by-Step |
| 46 | +**Goal:** Remove duplicates from the sorted array `[1, 1, 2, 3, 3]` in-place. |
| 47 | + |
| 48 | +```plaintext |
| 49 | +Data: 1 1 2 3 3 |
| 50 | + ------------------------- |
| 51 | +Step 1: [1] [1] 2 3 3 (Slow=0, Fast=1. Values match! Fast moves right.) |
| 52 | + ^S ^F |
| 53 | +
|
| 54 | +Step 2: [1] 1 [2] 3 3 (Fast found a '2'. It's unique!) |
| 55 | + ^S ^F (Action: Move Slow right, copy Fast's value to Slow) |
| 56 | +
|
| 57 | +Step 3: 1 [2] 2 [3] 3 (Array is now [1, 2, 2, 3, 3]) |
| 58 | + ^S ^F (Fast found a '3'. It's unique!) |
| 59 | + (Action: Move Slow right, copy Fast's value to Slow) |
| 60 | +
|
| 61 | +Step 4: 1 2 [3] 3 [3] (Array is now [1, 2, 3, 3, 3]) |
| 62 | + ^S ^F (Values match. Fast moves right, hits end.) |
| 63 | +
|
| 64 | +Result: The unique elements are everything from index 0 up to the Slow pointer: [1, 2, 3]. |
| 65 | +``` |
| 66 | + |
| 67 | +### Comparison Summary |
| 68 | +| Feature | Opposite Ends (Collision) | Same Direction (Trailing) | |
| 69 | +|---------|---------------------------|---------------------------| |
| 70 | +| **Setup** | `Left` at start, `Right` at end. | `Slow` at start, `Fast` at start. | |
| 71 | +| **Requirement** | Array MUST usually be sorted. | Array doesn't always need to be sorted (depends on problem). | |
| 72 | +| **Primary Action** | Pointers step toward each other. | Fast pointer pulls ahead of the slow pointer. | |
| 73 | +| **Used For...** | Target sums, valid palindromes, reversing strings. | Removing duplicates in-place, filtering elements. | |
0 commit comments