ConceptDifficulty: Intermediate2 min

Two Pointers: Closing In From Both Ends of a Sorted Array

In a sorted array, a sum that is too small can only grow by moving the left pointer, so every step rules out a whole row of pairs.

The two pointers pattern walks one array with two indices, called pointers, and moves one of them at every step, so a question about pairs is answered in a single pass. The cues are properties of the problem: the input is sorted, or can be sorted without losing the answer, and the question asks about a pair or a triple of values; or an array must be rewritten in place without a second array.

The first form starts one pointer at each end of a sorted array and moves them towards each other. To find two values that add up to a target, compare the sum at the pointers with it. A sum that is too small cannot be fixed by moving the right pointer, because every value to its left is smaller still, so the left pointer moves right. A sum that is too large moves the right pointer left for the same reason. Each move rules out every pair the discarded value could have made, which keeps one invariant: no pair outside the two pointers can be the answer.

The values 2 5 7 8 12 15 hold a pair that adds up to 19.

Which pair do the pointers find, and after how many moves?

7 and 12, at indices 2 and 4, after three moves. The trace shows each sum and the move it causes.

Opposite ends on 2 5 7 8 12 15 for the target 19

Inputvalues 2 5 7 8 12 15, target 19

  1. Step 1

    1. 2left
    2. 5
    3. 7
    4. 8
    5. 12
    6. 15right

    2 + 15 = 17, too small: left moves right

  2. Step 2

    1. 2
    2. 5left
    3. 7
    4. 8
    5. 12
    6. 15right

    5 + 15 = 20, too large: right moves left

  3. Step 3

    1. 2
    2. 5left
    3. 7
    4. 8
    5. 12right
    6. 15

    5 + 12 = 17, too small: left moves right

  4. Step 4

    1. 2
    2. 5
    3. 7left
    4. 8
    5. 12right
    6. 15

    7 + 12 = 19, found

ResultThe pair is 7 and 12, at indices 2 and 4.

Each step moves one pointer one place and the pointers never cross, so the pass takes at most n − 1 steps for n values: O(n) time and O(1) extra space, against O(n²) for checking every pair.

Spending a gift voucher on two items from a menu ordered by price works the same way. With too little spent, swap the cheap item for the next dearer one; with too much, swap the dear item for the next cheaper one. The likeness breaks at going back: a diner can return to an item already turned down, and a pointer never moves back, which is safe only because the sorted order proved that item useless.

The second form moves both pointers in the same direction. A read pointer visits every value, and a write pointer marks the next free slot for a value worth keeping, so an array can be filtered in place. When the input is not sorted and sorting would lose the indices, a hash map of complements finds the pair instead, as the Hash Map Patterns topic shows.