The Two Pointer Template: Why One Pattern Covers 30+ Problems
The two pointer template is the single most versatile pattern you will encounter on LeetCode. It shows up in arrays, strings, linked lists, and even tree problems — and once you internalize the three core variants, you can solve over 30 problems without inventing a new approach each time.
Most candidates treat each two-pointer problem as a standalone puzzle. That is a mistake. There are exactly three variants: opposite-direction pointers that converge from both ends, same-direction pointers where one leads and the other trails, and fast/slow pointers for linked list cycle and midpoint detection.
In this guide you will get the reusable template for each variant, see the classic LeetCode problems that map to each one, and learn a decision framework so you can identify which variant to use in under 30 seconds during an interview.
Variant 1: Opposite Direction Two Pointers
Opposite-direction two pointers is the most intuitive variant. You place one pointer at the start of the array and one at the end, then move them toward each other based on a condition. The loop ends when they meet or cross.
The core template looks like this: initialize left = 0 and right = n - 1. While left is less than right, compute your result, then move whichever pointer produces a less optimal result. If you need a larger value, move the pointer at the smaller element. If you need a smaller sum, move the pointer at the larger element.
This variant works because the sorted order (or the geometric structure of the problem) guarantees that moving one pointer eliminates a set of candidates that cannot be optimal. You never need to check them, which is why you go from O(n^2) brute force to O(n).
- Two Sum II (#167) — sorted array, find a pair that sums to target. Move left up if sum is too small, right down if too large.
- Container With Most Water (#11) — find two lines that maximize area. Move the pointer at the shorter line inward.
- Valid Palindrome (#125) — check if a string reads the same forwards and backwards. Compare characters at left and right, move both inward.
- Trapping Rain Water (#42) — compute trapped water using left and right boundaries converging toward the center.
- Three Sum (#15) — fix one element, then use opposite-direction two pointers on the remaining sorted subarray.
Pro Tip
When you see "sorted array" + "find a pair", it's always opposite-direction two pointers. When you see "remove in-place" or "partition", it's same-direction. This instant recognition saves minutes in interviews.
Variant 2: Same Direction Pointers for In-Place Operations
Same-direction two pointers — sometimes called the read/write pointer technique — is the go-to pattern whenever you need to remove, partition, or deduplicate elements in an array in-place. Both pointers start at the beginning and move forward, but the slow pointer only advances when a condition is met.
The template: initialize slow = 0. Iterate fast from 0 to n - 1. When the element at fast meets your condition (it is not a duplicate, it is not the value to remove, etc.), copy it to the slow position and increment slow. At the end, slow tells you the length of the modified array.
This variant runs in O(n) time and O(1) space. It works because the fast pointer scans every element exactly once, while the slow pointer marks the boundary of the "good" portion of the array. Elements before slow are your result; elements at or after slow are discarded.
- Remove Duplicates from Sorted Array (#26) — slow tracks the last unique position, fast scans for the next unique element.
- Move Zeroes (#283) — slow marks the next non-zero position, fast finds non-zero elements to swap forward.
- Remove Element (#27) — slow marks the write position, fast skips elements equal to the target value.
- Sort Colors (#75) — a three-pointer variant (low, mid, high) that partitions the array into three regions in a single pass.
Variant 3: Fast and Slow Pointers on Linked Lists
Fast and slow pointers — also known as the tortoise and hare algorithm — are designed specifically for linked list problems. The slow pointer moves one node at a time, the fast pointer moves two. This speed difference lets you detect cycles, find the middle node, and locate the nth node from the end.
For cycle detection (LeetCode #141), if there is a cycle, the fast pointer will eventually lap the slow pointer and they will meet inside the cycle. If fast reaches null, there is no cycle. To find the cycle entry point (#142), reset one pointer to the head after they meet, then move both one step at a time — they will meet at the cycle start.
For finding the middle of a linked list (#876), when the fast pointer reaches the end, the slow pointer will be exactly at the midpoint. This works because fast travels twice as far as slow. For finding the nth node from the end (#19), start fast n steps ahead of slow, then move both one step at a time until fast reaches the end — slow will be at the target.
- Linked List Cycle (#141) — detect whether a cycle exists. Fast moves 2, slow moves 1. If they meet, cycle exists.
- Linked List Cycle II (#142) — find the node where the cycle begins using the mathematical meeting-point property.
- Middle of the Linked List (#876) — when fast reaches the end, slow is at the middle.
- Remove Nth Node From End of List (#19) — offset fast by n steps, then advance both until fast hits null.
- Palindrome Linked List (#234) — find the middle with fast/slow, reverse the second half, then compare.
Did You Know
Two pointers appears in more LeetCode problems than any other single pattern — it's used in arrays (Two Sum II), strings (Valid Palindrome), linked lists (Cycle Detection), and even trees (BST validation with inorder).
How to Choose the Right Two Pointer Variant
Choosing the correct two pointer template in an interview comes down to recognizing three signals in the problem statement. Each signal maps directly to one variant, and with practice you can make this decision in seconds.
If the input is a sorted array or string and the problem asks you to find a pair, triplet, or boundary that satisfies a condition, use opposite-direction pointers. The sorted order is the key signal — it guarantees that moving one pointer eliminates invalid candidates.
If the problem asks you to modify an array in-place — remove elements, deduplicate, or partition — use same-direction pointers. The signal is the phrase "in-place" or "O(1) extra space." You need a read pointer and a write pointer moving in the same direction.
If you are working with a linked list and need to detect a cycle, find the middle, or locate a position relative to the end, use fast/slow pointers. The signal is "linked list" combined with "cycle," "middle," or "nth from end."
- "Sorted array" + "find a pair/triplet" → Opposite direction pointers
- "Remove in-place" or "partition" or "deduplicate" → Same direction pointers
- "Linked list" + "cycle" or "middle" or "nth from end" → Fast/slow pointers
- "Palindrome check" on array/string → Opposite direction; on linked list → Fast/slow + reverse
- "Maximize/minimize between two boundaries" → Opposite direction (greedy elimination)
Common Two Pointer Mistakes That Cost You Interviews
The two pointer technique explained in templates looks deceptively simple, but there are recurring mistakes that trip up even experienced candidates. Knowing these pitfalls in advance saves you from silent bugs that pass some test cases but fail on edge inputs.
The most frequent mistake in opposite-direction problems is moving the wrong pointer. In Container With Most Water, you must move the pointer at the shorter line. Moving the taller line can never increase the area — the water level is limited by the shorter side. If you move the wrong one, you skip the optimal solution entirely.
In same-direction problems, the common bug is an off-by-one error at the boundaries. After the loop, slow points to the length of the valid portion, not the last valid index. Returning slow instead of slow - 1 (or vice versa) is a classic source of wrong answers.
For fast/slow pointer problems, forgetting to handle the edge case where the list is empty or has only one node leads to null pointer exceptions. Always check that both head and head.next exist before entering the loop. Another subtle bug is using the wrong meeting-point logic for cycle entry — you must reset only one pointer to the head, not both.
Watch Out
The most common two-pointer bug is moving the wrong pointer — in opposite-direction, always move the pointer that produces a less optimal result. In same-direction, only advance the fast pointer when the condition is met.
Practice Strategy: 9 Problems to Master All Three Variants
The fastest way to internalize the two pointer interview template is to solve three problems per variant — nine problems total — in a specific order. Start with opposite-direction because it is the most intuitive, then move to same-direction, and finish with fast/slow on linked lists.
For opposite direction, solve Two Sum II (#167), Valid Palindrome (#125), and Container With Most Water (#11) in that order. Two Sum II teaches the basic convergence logic, Valid Palindrome adds string handling, and Container With Most Water introduces the greedy pointer-movement proof.
For same direction, solve Remove Duplicates (#26), Move Zeroes (#283), and Sort Colors (#75). These three problems build on each other — #26 is the pure template, #283 adds swapping, and #75 extends to three pointers.
For fast/slow, solve Linked List Cycle (#141), Middle of the Linked List (#876), and Palindrome Linked List (#234). Cycle detection is the foundation, middle-finding is a direct application, and palindrome checking combines fast/slow with list reversal.
After solving all nine, use YeetCode flashcards to review the templates weekly. The goal is not to memorize solutions — it is to build instant pattern recognition so you identify the right variant within seconds of reading a new problem.