Use two pointers moving towards each other or in the same direction to solve array problems efficiently
The two pointers pattern uses two indices to traverse an array or string, either from opposite ends moving towards each other, or both starting from the same position moving at different speeds. This technique reduces time complexity from O(n²) to O(n) for many problems.
Use this pattern when dealing with sorted arrays, finding pairs with specific properties, partitioning arrays, or when you need to compare elements from different positions. It's particularly effective for problems involving palindromes, removing duplicates, or finding subarrays with certain properties.
Two pointers start at opposite ends and move toward each other
def opposite_direction(arr, target):
left, right = 0, len(arr) - 1
while left < right:
current = arr[left] + arr[right]
if current == target:
return [left, right]
elif current < target:
left += 1
else:
right -= 1
return None
Both pointers start at the beginning and move at different speeds
def same_direction(arr):
slow = 0
for fast in range(len(arr)):
if arr[fast] != 0: # Keep non-zero elements
arr[slow], arr[fast] = arr[fast], arr[slow]
slow += 1
return slow # New length
Use three or more pointers for complex partitioning or multi-way comparisons
def three_pointers(arr, target):
arr.sort()
result = []
for i in range(len(arr) - 2):
if i > 0 and arr[i] == arr[i-1]:
continue
left, right = i + 1, len(arr) - 1
while left < right:
total = arr[i] + arr[left] + arr[right]
if total == target:
result.append([arr[i], arr[left], arr[right]])
left += 1
right -= 1
while left < right and arr[left] == arr[left-1]:
left += 1
elif total < target:
left += 1
else:
right -= 1
return result
def two_pointers(arr):
left, right = 0, len(arr) - 1
while left < right:
# Process current pair
current_sum = arr[left] + arr[right]
if current_sum == target:
return [left, right]
elif current_sum < target:
left += 1 # Need larger sum
else:
right -= 1 # Need smaller sum
return [] # Not found
Each pointer traverses the array at most once, resulting in linear time complexity.
Only uses pointer variables regardless of input size, achieving constant space.