|
| 1 | +# Two-Pointer Technique |
| 2 | + |
| 3 | +--- |
| 4 | + |
| 5 | +- The two-pointer technique is a popular algorithmic strategy used to solve various problems efficiently. This technique involves using two pointers (or indices) to traverse through data structures such as arrays or linked lists. |
| 6 | +- The pointers can move in different directions, allowing for efficient processing of elements to achieve the desired results. |
| 7 | + |
| 8 | +## Common Use Cases |
| 9 | + |
| 10 | +1. **Finding pairs in a sorted array that sum to a target**: One pointer starts at the beginning and the other at the end. |
| 11 | +2. **Reversing a linked list**: One pointer starts at the head, and the other at the next node, progressing through the list. |
| 12 | +3. **Removing duplicates from a sorted array**: One pointer keeps track of the unique elements, and the other traverses the array. |
| 13 | +4. **Merging two sorted arrays**: Two pointers are used to iterate through the arrays and merge them. |
| 14 | + |
| 15 | +## Example 1: Finding Pairs with a Given Sum |
| 16 | + |
| 17 | +### Problem Statement |
| 18 | + |
| 19 | +Given a sorted array of integers and a target sum, find all pairs in the array that sum up to the target. |
| 20 | + |
| 21 | +### Approach |
| 22 | + |
| 23 | +1. Initialize two pointers: one at the beginning (`left`) and one at the end (`right`) of the array. |
| 24 | +2. Calculate the sum of the elements at the `left` and `right` pointers. |
| 25 | +3. If the sum is equal to the target, record the pair and move both pointers inward. |
| 26 | +4. If the sum is less than the target, move the `left` pointer to the right to increase the sum. |
| 27 | +5. If the sum is greater than the target, move the `right` pointer to the left to decrease the sum. |
| 28 | +6. Repeat the process until the `left` pointer is not less than the `right` pointer. |
| 29 | + |
| 30 | +### Example Code |
| 31 | + |
| 32 | +```python |
| 33 | +def find_pairs_with_sum(arr, target): |
| 34 | + left = 0 |
| 35 | + right = len(arr) - 1 |
| 36 | + pairs = [] |
| 37 | + |
| 38 | + while left < right: |
| 39 | + current_sum = arr[left] + arr[right] |
| 40 | + |
| 41 | + if current_sum == target: |
| 42 | + pairs.append((arr[left], arr[right])) |
| 43 | + left += 1 |
| 44 | + right -= 1 |
| 45 | + elif current_sum < target: |
| 46 | + left += 1 |
| 47 | + else: |
| 48 | + right -= 1 |
| 49 | + |
| 50 | + return pairs |
| 51 | + |
| 52 | +# Example usage |
| 53 | +arr = [1, 2, 3, 4, 5, 6, 7, 8, 9] |
| 54 | +target = 10 |
| 55 | +result = find_pairs_with_sum(arr, target) |
| 56 | +print("Pairs with sum", target, "are:", result) |
| 57 | + ``` |
| 58 | + |
| 59 | +## Example 2: Removing Duplicates from a Sorted Array |
| 60 | + |
| 61 | +### Problem Statement |
| 62 | +Given a sorted array, remove the duplicates in place such that each element appears only once and return the new length of the array. |
| 63 | + |
| 64 | +### Approach |
| 65 | +1. If the array is empty, return 0. |
| 66 | +2. Initialize a slow pointer at the beginning of the array. |
| 67 | +3. Use a fast pointer to traverse through the array. |
| 68 | +4. Whenever the element at the fast pointer is different from the element at the slow pointer, increment the slow pointer and update the element at the slow pointer with the element at the fast pointer. |
| 69 | +5. Continue this process until the fast pointer reaches the end of the array. |
| 70 | +6. The slow pointer will indicate the position of the last unique element. |
| 71 | + |
| 72 | +### Example Code |
| 73 | + |
| 74 | +```python |
| 75 | +def remove_duplicates(arr): |
| 76 | + if not arr: |
| 77 | + return 0 |
| 78 | + |
| 79 | + slow = 0 |
| 80 | + |
| 81 | + for fast in range(1, len(arr)): |
| 82 | + if arr[fast] != arr[slow]: |
| 83 | + slow += 1 |
| 84 | + arr[slow] = arr[fast] |
| 85 | + |
| 86 | + return slow + 1 |
| 87 | + |
| 88 | +# Example usage |
| 89 | +arr = [1, 1, 2, 2, 3, 4, 4, 5] |
| 90 | +new_length = remove_duplicates(arr) |
| 91 | +print("Array after removing duplicates:", arr[:new_length]) |
| 92 | +print("New length of array:", new_length) |
| 93 | +``` |
| 94 | +# Advantages of the Two-Pointer Technique |
| 95 | + |
| 96 | +Here are some key benefits of using the two-pointer technique: |
| 97 | + |
| 98 | +## 1. **Improved Time Complexity** |
| 99 | + |
| 100 | +It often reduces the time complexity from O(n^2) to O(n), making it significantly faster for many problems. |
| 101 | + |
| 102 | +### Example |
| 103 | +- **Finding pairs with a given sum**: Efficiently finds pairs in O(n) time. |
| 104 | + |
| 105 | +## 2. **Simplicity** |
| 106 | + |
| 107 | +The implementation is straightforward, using basic operations like incrementing or decrementing pointers. |
| 108 | + |
| 109 | +### Example |
| 110 | +- **Removing duplicates from a sorted array**: Easy to implement and understand. |
| 111 | + |
| 112 | +## 3. **In-Place Solutions** |
| 113 | + |
| 114 | +Many problems can be solved in place, requiring no extra space beyond the input data. |
| 115 | + |
| 116 | +### Example |
| 117 | +- **Reversing a linked list**: Adjusts pointers within the existing nodes. |
| 118 | + |
| 119 | +## 4. **Versatility** |
| 120 | + |
| 121 | +Applicable to a wide range of problems, from arrays and strings to linked lists. |
| 122 | + |
| 123 | +### Example |
| 124 | +- **Merging two sorted arrays**: Efficiently merges using two pointers. |
| 125 | + |
| 126 | +## 5. **Efficiency** |
| 127 | + |
| 128 | +Minimizes redundant operations and enhances performance, especially with large data sets. |
| 129 | + |
| 130 | +### Example |
| 131 | +- **Partitioning problems**: Efficiently partitions elements with minimal operations. |
| 132 | + |
0 commit comments