Two Pointers
Two pointers is a technique where you use two indices to scan an array or linked list, typically moving them toward each other or at different speeds. It often turns O(n^2) solutions into O(n).
Why It Matters
Two pointers is one of the most common patterns for array and string problems. It’s simple, efficient, and shows up constantly in practice and interviews.
Patterns
1. Opposite Ends (converging)
Start one pointer at the beginning and one at the end. Move them toward each other.
# Is a string a palindrome?
def is_palindrome(s: str) -> bool:
lo, hi = 0, len(s) - 1
while lo < hi:
if s[lo] != s[hi]:
return False
lo += 1
hi -= 1
return True
assert is_palindrome("racecar") == True
assert is_palindrome("hello") == False
# Two sum on sorted array — O(n) instead of O(n^2)
def two_sum_sorted(nums: list[int], target: int) -> tuple:
lo, hi = 0, len(nums) - 1
while lo < hi:
s = nums[lo] + nums[hi]
if s == target:
return (lo, hi)
elif s < target:
lo += 1
else:
hi -= 1
return ()
assert two_sum_sorted([1, 3, 5, 7, 9], 8) == (0, 4) # 1 + 7... wait
assert two_sum_sorted([1, 3, 5, 7, 9], 12) == (1, 4) # 3 + 92. Fast and Slow
Both pointers start at the beginning. One moves faster than the other.
# Detect cycle in linked list (Floyd's algorithm)
def has_cycle(head) -> bool:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
return False
# Remove duplicates from sorted array in-place
def remove_duplicates(nums: list[int]) -> int:
if not nums:
return 0
slow = 0
for fast in range(1, len(nums)):
if nums[fast] != nums[slow]:
slow += 1
nums[slow] = nums[fast]
return slow + 1 # length of unique prefix
nums = [1, 1, 2, 2, 3, 4, 4]
length = remove_duplicates(nums)
assert nums[:length] == [1, 2, 3, 4]3. Sliding Window (two pointers variant)
See Sliding Window for the full pattern. The left and right pointers define a window.
When to Use
- Problem involves sorted array or linked list
- Need to find pairs with a certain sum
- Remove duplicates in-place
- Detect cycles
- Partition or rearrange arrays
- Compare two sequences
Complexity
Usually O(n) time and O(1) space — each pointer traverses the array at most once.
Related
- Binary Search — another sorted-array technique
- Sliding Window — extension of two pointers
- Arrays — primary data structure for this pattern
- Linked Lists — fast/slow pointer for cycle detection