Two Pointer
Comprehensive documentation for implementing the two pointer technique in algorithmic problem solving
Introduction
Two pointer technique is an algorithmic pattern that leverages two indices to traverse data structures efficiently, primarily used for optimization problems involving arrays and linked lists.
Most implementations require a sorted data structure for correct functionality. Time complexity includes O(n log n)
for the sorting operation when required.
Implementation
Pattern 1: Opposite Direction Traversal
def find_target_sum(numbers: List[int], target: int) -> Optional[Tuple[int, int]]:
"""
Finds two numbers in a sorted array that sum to the target value.
Args:
numbers: Sorted array of integers
target: Target sum to find
Returns:
Tuple of two numbers that sum to target, or None if not found
"""
left, right = 0, len(numbers) - 1
while left < right:
current_sum = numbers[left] + numbers[right]
if current_sum == target:
return (numbers[left], numbers[right])
elif current_sum < target:
left += 1
else:
right -= 1
return None
Pattern 2: Same Direction Traversal
Implementation Consideration:
Same direction traversal requires careful boundary condition management to prevent pointer overlap or array out-of-bounds access.
from typing import List
def remove_duplicates(array: List[int]) -> int:
"""
Removes duplicates from a sorted array in-place.
Args:
array: Sorted array of integers
Returns:
Length of array after removing duplicates
"""
if not array:
return 0
write_index = 1
for read_index in range(1, len(array)):
if array[read_index] != array[read_index - 1]:
array[write_index] = array[read_index]
write_index += 1
return write_index
Implementation Pattern
1. Input Validation
Implement robust input validation to handle edge cases such as empty arrays, single elements, and invalid inputs. Define clear preconditions and postconditions.
2. Pointer Initialization
Initialize pointers based on the traversal pattern required. Ensure initial positions are valid and maintain necessary invariants throughout execution.
3. Movement Logic
Define clear conditions for pointer movement. Implement boundary checks and ensure pointers maintain their relative positions according to the algorithm requirements.
4. Termination Conditions
Establish explicit termination conditions to prevent infinite loops. Include both success and failure conditions in the implementation.
Critical Considerations:
- Implement boundary checks for array access
- Handle null/undefined inputs appropriately
- Validate preconditions before execution
- Consider thread safety in concurrent environments
Implementation Variants
Standard Two Pointer
def standard_pattern(array):
left = 0
right = len(array) - 1
while left < right:
# Process elements
left += 1
right -= 1
Fast-Slow Pointer
def fast_slow_pattern(array):
slow = 0
fast = 0
while fast < len(array):
# Process elements
slow += 1
fast += 2
Testing Strategy
Unit Tests
Implement comprehensive unit tests covering edge cases, boundary conditions, and typical usage patterns.
Integration Tests
Test interaction with sorting algorithms and data structure implementations.
Performance Tests
Validate time and space complexity requirements under various input conditions.