The two-pointer technique replaces a nested loop with two index variables that move through a structure with intent, instead of checking every pair. It shows up constantly in interviews because the insight — that moving one side can only help, never hurt, given the right structure — is not obvious the first time you see it, but becomes second nature after a handful of problems.
What changed in 2026
- It remains paired with the sliding window algorithm as the two most-tested array-technique patterns in coding interviews, precisely because so many problems reduce to one or the other.
- Fast-slow pointer problems (cycle detection, middle-of-list) stay a fixture of linked-list interview questions, since they solve real problems in O(1) space where a hash-set approach would need O(n).
- AI-assisted interview prep tools now explicitly tag problems by pattern (two-pointer, sliding window, backtracking), which has made pattern recognition, not memorization, the thing people actually study.
Two flavors: opposite-direction and same-direction
Opposite-direction pointers start at both ends of a sorted structure and move inward, typically on array problems like finding a pair that sums to a target. Same-direction pointers both start near the beginning and move forward at different speeds or for different purposes — this covers fast-slow cycle detection and in-place array partitioning alike. Unlike a sliding window, which maintains one contiguous range and updates a running value, two-pointer problems do not always define a window at all.
Opposite-direction pointers
def two_sum_sorted(nums, target):
left, right = 0, len(nums) - 1
while left < right:
s = nums[left] + nums[right]
if s == target:
return left, right
elif s < target:
left += 1
else:
right -= 1
return -1, -1
This requires sorted input — the logic only holds because moving left forward can only increase the sum, and moving right back can only decrease it.
Fast-slow pointers
def has_cycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
return False
The fast pointer moves twice as far each step. If there is a cycle, it eventually laps the slow pointer; if there is no cycle, it reaches the end first.
The patterns compared
| Pattern |
Pointers move |
Classic problem |
Complexity |
| Opposite-direction |
Start and end, move inward |
Two-sum on sorted array, palindrome check |
O(n) time, O(1) space |
| Same-direction (fast-slow) |
Both start at head, different speeds |
Cycle detection, find middle of a list |
O(n) time, O(1) space |
| Same-direction (read/write) |
One scans, one marks write position |
Remove duplicates in place |
O(n) time, O(1) space |
| Sliding window |
Contiguous, incrementally updated range |
Longest substring without repeats |
O(n) time, O(1)-O(k) space |
Common pitfalls
Using opposite-direction pointers on unsorted data. The technique depends entirely on the sorted-order guarantee; without it, the answer is simply wrong, not just slow.
Off-by-one on the loop condition. left < right versus left <= right changes whether a middle element gets compared against itself.
Skipping null checks in fast-slow patterns. Check both fast and fast.next before advancing, or the walk dereferences past the end of the list.
FAQ
Is this the same kind of pointer as in C or Rust?
No. In this context a pointer is an index into an array or a reference used to walk a linked list, not a raw memory address. The name is a borrowed analogy, not the same mechanism.
When should I use two-pointer instead of a sliding window?
When the two positions do not define one contiguous, incrementally updated range — for example, moving inward from both ends of a sorted array, or running two references at different speeds through a linked list.
Does two-pointer always require sorted input?
Only the opposite-direction pattern typically does. Fast-slow patterns like cycle detection do not care about order at all.
Why is this considered an easy optimization to miss?
Because the brute-force nested-loop version also produces a correct answer, just slower — the two-pointer insight is not obvious until the pattern has been seen before.
Where to go next