Elman Huseynov
Tech Interviews

The Two-Pointer Technique and the Problems It Solves

5 min read

Related service: Mock interviews

Episode 31. One idea, 3 shapes, clear tells

The two pointer technique is 1 idea in 3 shapes. Pointers converging from both ends of a sorted array.

A slow boundary and a fast scanner rewriting an array in place. A fast pointer lapping a slow one to detect a cycle.

Classify the shape first. The code is about 10 lines, in Python or anything else.

Candidates who memorise 40 problems freeze at the 41st. Those who know the 3 shapes derive it in a minute.

The three shapes of the two pointer technique: converging from both ends, a slow boundary with a fast scanner, and a fast pointer lapping a slow one
The 3 shapes of the two pointer technique

Why does the two pointer technique exist?

A nested loop over n items costs n squared comparisons. Two pointers gets the same answer in n.

The technique works only when the array carries an ordering you can trust.

Moving 1 pointer then says something certain about every position skipped.

No order, and no way to create one? The pattern does not apply. Recognising that fast is worth as much.

Nested loop costs 1,000,000 comparisons on 1,000 items; the two pointer technique costs 1,000
Why two pointers beats the nested loop

Shape 1: pointers moving toward each other

Start at both ends. Move the one that cannot improve the answer.

def two_sum_sorted(nums, target):
    lo, hi = 0, len(nums) - 1
    while lo < hi:
        s = nums[lo] + nums[hi]
        if s == target:
            return lo, hi
        if s < target:
            lo += 1
        else:
            hi -= 1
    return None

The reasoning matters more than the code. Sum too small? Every pair using this lo with a smaller hi is too small as well.

One step eliminated a whole row of the comparison table.

Same shape: container with most water, valid palindrome, 3Sum after sorting, trapping rain water.

The tell: the answer is a pair, and the array is sorted or can be.

Shape 2: same direction, different speeds

The fast pointer explores. The slow one marks the boundary of the answer.

def dedupe(nums):
    if not nums:
        return 0
    slow = 0
    for fast in range(1, len(nums)):
        if nums[fast] != nums[slow]:
            slow += 1
            nums[slow] = nums[fast]
    return slow + 1

State the invariant: everything at or before slow is correct and final. It answers most follow-ups in advance.

Same shape: move zeroes, remove element, partition around a pivot.

The tell: an in-place rewrite where the output is a prefix of the array.

Shape 3: cycle detection in a linked list

One pointer twice as fast. If there is a loop, the fast one laps the slow one.

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 follow-up is always where the cycle starts. Reset 1 pointer to the head, advance both by 1. They meet at the entry.

Same shape: find the duplicate number, happy number, middle of a linked list.

The tell: a sequence that can repeat, and no extra memory allowed.

How do you tell which shape a problem needs?

Read the output. A pair from a sorted array is shape 1. An in-place rewrite is shape 2.

A repeating sequence with no extra memory is shape 3. Spend 2 minutes on this choice before you write any code at all.

Four steps to classify a two pointer problem: read the output, name the shape, state the invariant, then write the code
Classify a two pointer problem in 2 minutes

What should you say in the first 30 seconds?

Name the pattern, the shape, and the correctness argument.

“This looks like two pointers. The array is sorted and I want a pair, so I start at both ends.”

The failure I see most is silence followed by code. Interviewers score the reasoning, so it has to be audible.

What are the 4 follow-up questions?

Complexity, and why. Linear. Neither pointer ever moves back.

What if the array is not sorted? Sorting costs n log n, still better than quadratic. Check it does not destroy original indices.

What about duplicates? After a match, advance past every equal value on both sides.

Without extra space? Usually the point of the question. Shapes 2 and 3 are both answers.

The four follow-up questions after a two pointer answer: complexity, unsorted input, duplicates, and extra space
The 4 follow-ups after a two pointer answer

How to practise two pointer problems

Take 6 problems, 2 per shape. Solve each 3 times: with help, from memory, out loud to a wall.

Grinding 40 problems teaches you 40 answers. I built AlgoPath around the shapes instead.

Common questions

When does the two pointer technique not apply?

When the array has no order, and you cannot create one without losing what matters. Classic Two Sum on an unsorted array wants original indices, which sorting throws away. So it is a hash map problem. Recognising that in 30 seconds is worth as much as knowing the pattern.

Do you need to prove why cycle detection works?

Know that the proof exists and be able to sketch it. Let the tail be length a. Let the meeting point be b steps into a cycle of length c. Slow walked a plus b. Fast walked twice that; the extra is whole laps. So a plus b is a multiple of c.

How do you handle duplicates in 3Sum?

After you record a match, advance past every equal value on both sides. Skipping neither side emits the same triple repeatedly. That is the failure I see most here. Do the same skip on the outer loop index. Otherwise you re-run the whole inner scan for an identical first element.

Is sorting first ever the wrong move?

When the question needs original positions. Or when the input is a stream you cannot hold. Sorting costs n log n, which still beats a quadratic scan. The cost is rarely the objection. Check what sorting destroys before you reach for it, and say that check out loud.

When do you use two pointers?

Use it when the input has an order you can exploit. A brute force would be quadratic; two pointers make it linear. Sorted arrays, linked lists and in-place rewrites are the usual cases. If moving one pointer tells you something reliable about the other, the pattern applies.

The short version

Two pointers works when order lets you skip positions safely. Sorted pair problems converge from both ends.

In-place rewrites use a slow boundary and a fast scanner. Cycle questions use 1 and 2 steps.

Classify first, out loud. Then write the invariant. Then write the code.

To have the pattern tested under pressure, book a mock interview. A written scorecard follows.

The technical loop is in the complete guide to FAANG technical interviews.