Two Pointers is one of the highest-ROI techniques for coding interviews. It is simple to implement and easy to reason about once you know the rules. This pattern appears frequently in array and string problems, such as finding pairs that meet a condition, reversing an array or string in place, checking whether a string is a palindrome, removing elements in place, and scanning efficiently without repeated work.
At its core, Two Pointers transforms a brute-force approach, such as comparing many pairs or rescanning the same section, into a linear process by maintaining two indices and changing them according to a clear rule. Instead of trying every possibility, you use the current values at those indices to decide which side to move next, and each move eliminates cases you no longer need to consider.
If you get comfortable with where two pointers apply and how to move the indices without breaking the logic, you will solve a wide range of interview problems efficiently and with fewer bugs.
What is the Two Pointers pattern?
As implied by the name, the two-pointer pattern refers to an algorithm that uses two variables (pointers) to keep track of two indices. These pointers are commonly left and right, inside the same data structure, and uses them together to enforce a rule.
A two-pointer solution has three defining properties:
- Two active positions: At every step, the algorithm reasons about the values at two indices.
- A movement rule: Based on those values, you choose how to move one or both pointers.
- No backtracking: Pointers move monotonically, either left or right, so the total work stays small.
Two-pointers help you avoid nested loops by ensuring each pointer only moves a limited number of times.
Strategies of two pointers
Two pointers is not a single fixed template. It is a family of techniques where two indices move through the input under a clear rule. The main advantage is that pointer movement replaces repeated scanning. Instead of restarting loops or checking the same positions multiple times, you move one or both pointers so that every step makes measurable progress. Once you learn the common strategies below, you can quickly map many interview problems to the right pointer behavior.
Inward traversal
In inward traversal, you place one pointer at the start of the array or string and the other at the end, then move them toward each other.
Each iteration compares or uses the values at left and right indexes to decide what to do next. The loop typically stops when the pointers meet or cross, because all relevant pairs or positions have been processed.
Unidirectional traversal
Unidirectional traversal uses two pointers that move at the same pace in the same direction, usually left to right, each with different responsibilities.
A read pointer scans every element to examine it, while a write pointer marks where the next valid element should be placed. This lets you remove, filter, or compact elements in place without extra arrays. The key is that the prefix up to write - 1 is always kept clean and valid, which makes the approach easy to reason about and implement.
Staged tarversal
In staged traversal, you do not advance both pointers together from the start. Instead, you begin by moving one pointer to reach a meaningful position, such as the first element that can start a valid pair, the first mismatch, or the first element that violates a constraint. Once that “trigger point” is reached, you start moving the second pointer to either catch up, form a valid pair, or rebuild a valid state. This creates a clear two-phase flow: first you locate where work needs to begin, then you use the second pointer to complete the job efficiently.
A common way to think about this is that the first pointer defines where we are in the scan, and the second pointer activates only when it is needed to satisfy the problem’s rule. After both pointers become active, they still move in one direction and never reset, so the total work remains linear.
Example: Valid palindrome
Let’s have a look at an example to understand two-pointers.
Goal: Determine whether a given string is a palindrome.
A naive approach to solving Valid Palindrome is to compare characters using nested loops. For each character from the left side, you search for its matching character on the right side while skipping non-alphanumeric characters and handling case differences. This repeatedly scans the same parts of the string, so the number of comparisons grows quickly as the input gets longer, resulting in O(n²) time in the worst case.
Two pointers optimize this by comparing the string at both ends simultaneously. We place one pointer at the start and one at the end, and compare the characters. If they match, we move both pointers inward and continue. Each pointer only moves forward or backward and never resets, so each character is processed at most once. That reduces the runtime to O(n) without using any extra space.
Let’s have a look at the following illustration to understand this algorithm better:
Python implementation
Now, let’s look at the optimized solution code for the valid palindrome problem.
What makes this a two-pointer problem?
leftandrightare both active in every comparison.- Each pointer move is justified. Skipping non-alphanumerics cannot change the answer. A mismatch means the answer is immediately
False. - Each pointer only moves inward, so the total work is linear.
Complexity analysis:
- The time complexity of this algorithm is O(n) because each pointer advances at most n steps.
- The space complexity of this algorithm is O(1) extra space.
When to use two pointers?
Two pointers work best when the problem naturally depends on two positions at once, and you can decide which pointer to move using a clear rule. Each move should have a purpose, such as fixing a mismatch, skipping irrelevant elements, or discarding pairs that cannot work. When that rule exists, two pointers avoid repeated scanning and often replace a nested loop with a single pass. The table below lists common signals that indicate when using two pointers is the right technique.
| Problem Signal | What It Usually Means | Why Two Pointers Help |
| You compare elements at two indices. | You need to evaluate two positions together, such as matching ends, reversing, or validating symmetry. | Two Pointers let you check both ends (or two positions) in one pass by moving the side that must change, instead of re-scanning. |
| You are asked for pairs. | You must find two elements that satisfy a condition, often more efficiently when the input is sorted. | With a clear movement rule, each pointer move discards impossible pairs, avoiding O(n²) pair checks. |
| You want in-place deletion. | You need to remove elements, compact valid values, or overwrite duplicates without extra arrays. | A read pointer scans once while a write pointer builds the valid prefix, so you update in place with O(1) extra space. |
| A single scan should be enough. | The brute-force approach rechecks the same region repeatedly (via nested loops or repeated passes). | Two pointers moves forward or inward without resets, so each index is processed a limited number of times for an overall linear scan. |
Identifying two pointers problem
Two Pointers is often mistaken for any solution that uses two indices, but simply having i and j does not make it a two-pointer solution in the interview sense.
Why does the confusion happen:
- Many solutions use
iandjin nested loops. That is still O(n2) time. - Some solutions reset pointers repeatedly, which re-scans the same elements.
- Some solutions move pointers without a clear rule, resulting in trial-and-error.
How to tell you are using the Two Pointers pattern:
- The movement rule is explicit: You can explain: if condition X holds, move left; otherwise move right.
- Each pointer moves monotonically: Pointers move inward or forward without resets.
- Each move discards candidates: After moving a pointer, you can justify why the skipped positions cannot lead to a valid answer.
If these are not true, the code might still be correct, but it is not using the technique that gives two-pointer algorithms their efficiency and clarity.
Common mistakes and how to avoid them
Two pointers is conceptually simple, but small implementation errors can lead to incorrect results. Some of the most common mistakes include:
- Moving a pointer without a reason: This can skip valid answers or cause infinite loops. You can avoid it by writing the movement rule in plain words before coding, such as: if the current value is too small, move
leftto increase it. - Off-by-one errors in loop conditions: Using the wrong condition can cause double comparisons or out-of-bounds access. You can avoid it by using
while left < rightcondition when comparing two ends or by only using<=when you intentionally need to process the center element. - Incorrect skipping logic: Skipping invalid characters or values can run past the other pointer. You can avoid it by always guarding skipping loops with
left < right, as in the palindrome example. - Breaking the invariant in read and write problems: If you move
writeat the wrong time, you can overwrite values you still need or leave empty spots. You can avoid it by keeping this simple rule: everything beforewriteis already correct. Only dowrite += 1after you place a valid value atnums[write].
Interview tips
Some common interview tips when using Two Pointers include the following:
- State the invariant clearly: For example, everything outside
[left, right]is already validated. - Justify every pointer move: You should be able to explain why moving that pointer cannot discard a correct answer.
- Explain why the runtime of two Pointers is O(n): Each pointer advances a limited number of times, so total pointer moves are linear.
- Handle edge cases early: Consider empty inputs, single-element inputs, and inputs where everything gets skipped or removed.