Patterns

What is Two Pointers?

Two pointers is an algorithmic pattern that uses two indices to traverse a data structure — usually an array or string — instead of one. The pointers move toward each other from opposite ends, or in the same direction at different speeds, letting you solve many problems in a single linear pass with constant extra space.

Time O(n)Space O(1)Topic Patterns

The core idea: two indices, one pass

Most beginners reach for nested loops when a problem involves comparing elements — check every element against every other, an O(n squared) sweep. The two pointers pattern replaces that with two indices that move through the data deliberately, so you visit each position roughly once. Instead of re-scanning the whole array to ask 'what pairs with element i?', you let the second pointer's position carry information about what you have already ruled out.

The trick is that each pointer moves in only one direction and never backtracks. Because neither index resets, the total number of steps is bounded by the length of the array — that is what turns a quadratic brute force into a linear scan.

Two shapes: converging and fast–slow

There are two common layouts. In the converging (opposite-ends) form, one pointer starts at index 0 and the other at the last index, and they walk toward each other until they meet. This suits pair-sum searches on sorted arrays, in-place reversal, and palindrome checks.

In the fast–slow (same-direction) form, both pointers start near the front but advance at different rates or under different conditions. A slow 'write' pointer trails a fast 'read' pointer to compact an array in place — removing duplicates or zeros — while a fast pointer moving two steps to a slow pointer's one detects cycles in a linked list (Floyd's algorithm). Watching the two indices crawl through the array step by step makes which shape you need click faster than reading the loop.

Why it works on sorted data

For pair-sum problems the converging pattern relies on order. When the array is sorted, the sum of the two ends tells you exactly which way to move: if the sum is too small, the only way to increase it is to move the left pointer right toward larger values; if it is too big, move the right pointer left. Each comparison eliminates one candidate for good, so a single pass suffices.

This is also why sorting is sometimes worth the O(n log n) cost up front: it unlocks the linear scan for problems like 3Sum, where you fix one element and two-point the rest. On unsorted data without that structure, a hash table is often the better tool.

pythonFind a pair summing to target in a sorted array with converging pointers.
def two_sum_sorted(nums, target):
    left, right = 0, len(nums) - 1
    while left < right:
        current = nums[left] + nums[right]
        if current == target:
            return [left, right]
        if current < target:
            left += 1      # sum too small, need a larger value
        else:
            right -= 1     # sum too big, need a smaller value
    return [-1, -1]        # no pair found
Time complexityO(n)
Space complexityO(1)

A single scan is O(n) time and O(1) extra space because neither pointer backtracks. If the input must be sorted first, the sort's O(n log n) dominates. Nested two-pointer variants like 3Sum are O(n squared).

When to use it

  • Searching a sorted array for a pair or triplet whose values meet a sum or difference condition
  • Reversing an array or string in place, or checking whether a string is a palindrome
  • Removing duplicates, zeros, or unwanted elements from a sorted array in place with a read/write pointer
  • Detecting a cycle or finding the midpoint of a linked list using fast and slow pointers

Watch out for

  • Applying the converging sum trick to unsorted data — the 'move left or right' logic only works when the array is sorted, and sorting first adds O(n log n).
  • Getting the loop condition wrong: using left <= right when an element must not pair with itself, or advancing the wrong pointer, which causes infinite loops or missed answers.
  • Forgetting to skip over duplicate values in problems like 3Sum, which produces repeated result tuples.
In the interview

Two pointers is one of the highest-frequency patterns in coding interviews, especially for array and string rounds at product companies and campus placement drives. Classic prompts include Two Sum II (sorted input), valid palindrome, reverse string, remove duplicates from a sorted array, container with most water, and 3Sum. Interviewers rarely say 'use two pointers' by name — they expect you to notice that a sorted input or an in-place requirement is the hint. What they are really watching is whether you can justify why each pointer moves the way it does, state the O(n) time and O(1) space out loud, and handle edge cases like empty input, duplicates, and the pointers crossing.

Two Pointers: frequently asked questions

Is two pointers hard to learn?

No — it is one of the more approachable patterns once you see it move. The logic is just two indices that never backtrack, and it clicks quickly when you watch them step through an array frame by frame. The harder part is recognizing when a problem is a two-pointer problem, which comes with practice.

When should I use two pointers instead of a hash table?

Reach for two pointers when the data is sorted or you need O(1) extra space, such as in-place reversal or dedup. Use a hash table when the input is unsorted and you can afford O(n) memory to look up complements in one pass. For Two Sum on an unsorted array a hash map is usually simpler; on a sorted array two pointers wins on space.

What is the time complexity of two pointers?

The scan itself is O(n) time and O(1) extra space, because each pointer traverses the array at most once. If you must sort the input first to use the pattern, the total becomes O(n log n), dominated by the sort. Nested variants like 3Sum are O(n squared).

What is the difference between two pointers and sliding window?

Sliding window is a specialized two-pointer technique where both pointers move in the same direction and the span between them represents a contiguous subarray or substring. Plain two pointers is broader — the indices can start at opposite ends and converge. If you are tracking a running window like a max sum or longest substring, that is sliding window.

See Two Pointers as an animated story

Reading the definition is one thing — watching two pointers run line by line, then explaining it to an AI interviewer, is how it actually sticks. That is what CodeStory does.