Pattern 02 of 20

Two Pointers

Walk two indices towards each other, or one behind the other, to avoid a nested loop.

When to use it

  • The input is sorted, or sorting it does not lose information
  • You compare elements from both ends (palindromes, pair sums)
  • You must rearrange an array in place

The idea

Two indices move through the array under a rule that never needs to look back. Because each pointer only advances, the whole scan is linear, and order (usually sorting) tells you which pointer to move.

Typical cost O(n) time after an optional O(n log n) sort, O(1) extra space.

How it works

Two pointers replace a pair of nested loops with two indices that only ever move forward (or inward). The trick is a rule that tells you, after one comparison, which pointer can safely advance without skipping a possible answer.

With a sorted array and pointers at both ends, the rule comes from order: if the sum is too small, the left element can never be part of a solution with anything to the right, so it is discarded. Each step rules out a whole row of the brute-force grid, which is why the scan is linear.

The second shape is reader and writer: a fast pointer reads every element while a slow pointer marks where the next kept element goes. This is how you remove, compact or partition in place with O(1) memory.

Spot it when the input is sorted, when you compare from both ends (palindromes, containers), or when the problem says 'in place'. If the input is unsorted but order does not matter, sorting first is often the move that unlocks it.

How to attack it

  1. 1Check whether the array is sorted, or whether sorting it loses nothing the answer needs.
  2. 2Pick the shape: opposite ends moving inward, or slow writer and fast reader.
  3. 3State the movement rule and why it never skips a valid answer.
  4. 4Define the loop condition precisely (left < right versus left <= right).
  5. 5Handle duplicates explicitly if the answer must be unique.

Template

A skeleton to adapt, not a solution to paste. Write it from memory a few times.

def pair_with_sum(nums, target):
    # nums must be sorted. Pointers start at both ends and move inward.
    left, right = 0, len(nums) - 1
    while left < right:
        total = nums[left] + nums[right]
        if total == target:
            return [left, right]
        if total < target:
            left += 1   # need a bigger sum: discard the smallest
        else:
            right -= 1  # need a smaller sum: discard the largest
    return []


def compact(nums, keep):
    # Slow pointer 'write' marks where the next kept element goes.
    write = 0
    for read in range(len(nums)):
        if keep(nums[read]):
            nums[write] = nums[read]
            write += 1
    return write  # new logical length

Variants

Opposite ends
Pair sums in sorted arrays, palindrome checks, container-with-most-water style problems where you move the weaker side.
Reader and writer
Remove elements, deduplicate a sorted array or move zeros to the end in place, keeping relative order.
Fix one, scan two
For triplets, fix the first element in a loop and run opposite-end pointers on the rest: O(n²) instead of O(n³).
Two sequences
One pointer per array to merge sorted lists, check a subsequence, or intersect two sorted inputs.
Three-way partition
Low, mid and high pointers split an array into three groups in one pass, as in sorting an array of three colors.

Pitfalls

  • Applying opposite-end pointers to unsorted input, where the movement rule no longer holds.
  • Skipping duplicates before recording an answer instead of after, or skipping them on only one side.
  • Using left <= right when an element must not pair with itself.
  • Sorting when the problem asks for original indices, without keeping the indices alongside the values.
  • Moving both pointers on every step when the rule says only one should move.

What it costs

OperationCost
Opposite-end scanO(n) time, O(1) space
Sort firstO(n log n) time, O(1) to O(n) space depending on the sort
Fix one plus two pointers (triplets)O(n²) time
Reader and writer compactionO(n) time, O(1) space

30 Two Pointers problems

Easiest first. Problems marked Free can be solved without Pro.

  1. 1Mirror Phrase CheckFreeEasy
  2. 2Sorted Ledger PairFreeEasy
  3. 3Merge Two Sorted FeedsFreeEasy
  4. 4Sorted Squares of ReadingsEasy
  5. 5Push Zeros to the BackEasy
  6. 6Vowel MirrorEasy
  7. 7Hidden in OrderEasy
  8. 8Typed With BackspacesEasy
  9. 9Common ReadingsEasy
  10. 10Keep At Most Two CopiesMedium
  11. 11Triplets That Hit the TargetMedium
  12. 12Widest ReservoirMedium
  13. 13Three-Bin SortMedium
  14. 14One Deletion PalindromeMedium
  15. 15Count Pairs Under BudgetMedium
  16. 16Closest Triplet SumMedium
  17. 17Quadruplets That Hit the TargetMedium
  18. 18Fewest RaftsMedium
  19. 19Triangle-Ready TripletsMedium
  20. 20Longest RidgeMedium
  21. 21Shortest Unsorted WindowMedium
  22. 22Closest Across Three ListsMedium
  23. 23Schedule OverlapsMedium
  24. 24Next ArrangementMedium
  25. 25Rainwater Between WallsHard
  26. 26Best Span Around a DayHard
  27. 27Shortest Cut to SortHard
  28. 28Shortest Window Holding a SequenceHard
  29. 29K-th Smallest GapHard
  30. 30Mirrored ChunksHard

Solve them in the browser, in Python or JavaScript.