Two Pointers
Introduction
The Two Pointers pattern involves iterating through an array using two references (pointers) that move toward each other, or move in the same direction at different speeds.
It is highly memory-efficient, usually operating entirely in-place (\(O(1)\) space).
How to Recognize It
Use Two Pointers when: - The input array is sorted. - You need to find pairs that sum to a target. - You need to reverse an array or string in-place. - You are comparing elements at opposite ends of an array (e.g., checking for palindromes).
Pattern 1: Opposite Ends (Converging)
Used when the array is sorted, or when you are comparing endpoints (like Palindromes or Container With Most Water).
def two_sum_sorted(nums, target):
left = 0
right = len(nums) - 1
while left < right:
current_sum = nums[left] + nums[right]
if current_sum == target:
return [left, right]
elif current_sum < target:
# We need a larger sum, move left pointer right
left += 1
else:
# We need a smaller sum, move right pointer left
right -= 1
return []
Pattern 2: Same Direction (Fast/Slow)
Used when modifying an array in place, like removing duplicates or moving zeroes to the end.
def move_zeroes(nums):
# 'slow' keeps track of where the next non-zero should go
slow = 0
# 'fast' scans the array
for fast in range(len(nums)):
if nums[fast] != 0:
# Swap them
nums[slow], nums[fast] = nums[fast], nums[slow]
slow += 1
(Note: Fast/Slow pointers are heavily used in Linked Lists to detect cycles. We cover this specifically in the Fast and Slow Pointers / LinkedList section).
Time and Space Complexity
- Time Complexity: \(O(N)\). The pointers scan the array at most once. (If you have to sort the array first, the total time becomes \(O(N \log N)\)).
- Space Complexity: \(O(1)\). You only need two integer variables for the pointers.
Summary
- If the array is sorted and you need pairs, put pointers at the
leftandrightends and converge. - If you need to mutate an array in-place by filtering elements, use a
slowpointer to track the insertion index, and afastpointer to scan. - Complexity is usually \(O(N)\) time and \(O(1)\) space.