As the name suggests, the two pointer technique consists of iterating an array with two indexes that move independently based on a condition.
This is useful for problems that require traversing the entire array efficiently, usually when working with pairs — e.g. comparisons, filtering, or sorting.
The implementation is very simple and straightforward:
- Define an index outside the main iteration loop
- Increment or decrement that index based on a given condition
There are three common variants, based on how the pointers move relative to each other: opposing, fast and slow, and sliding window.
TIP
Use
forwhen iterating over a known sequence or range. Usewhilewhen the stopping condition depends on something that changes during execution.
Opposing pointers
The pointers start at opposite ends of the array and move toward each other.
For example, this is an implementation for reversing a string in-place using two pointers:
def reverse_string(s: str) -> None:
left = 0
right = len(s)-1
while left < right:
s[left], s[right] = s[right], s[left]
left += 1
right -= 1NOTE
See 344. Reverse String on LeetCode.
Fast and slow pointers
Both pointers move in the same direction but at different speeds. The classic use is cycle detection on a linked list: if the fast pointer ever meets the slow one, there’s a cycle.
Sliding window
Another variation of the two pointer approach is the sliding window.
The main difference is that both indexes move in the same direction; what matters is what's between them.
It’s useful when you need to work with subarrays and track properties like length, sum, or average.
Fixed-size window
The window length stays constant. Slide it forward one step at a time, updating the aggregate by adding the new element and removing the one that fell off.
def find_max_average(nums: list[int], k: int) -> float:
window_sum = sum(nums[:k])
max_sum = window_sum
for i in range(k, len(nums)):
window_sum += nums[i] - nums[i - k]
if window_sum > max_sum:
max_sum = window_sum
return max_sum / kNOTE
See 643. Maximum Average Subarray I on LeetCode.
TIP
What makes this technique efficient is maintaining state as the pointers move, rather than recomputing it from scratch on each step. That’s how the nested loop collapses into a single linear pass.
Variable-size window
The window grows and shrinks based on a condition: right expands it, left contracts it whenever the condition breaks. Useful for “longest/shortest subarray that satisfies X” problems.