Android & iPhone apps are coming soon. Log in for a plan and reminders made for you →

Know this before you start: “Same direction: slow and fast pointers”

Two pointers moving the same way

A fast pointer reads every item; a slow pointer marks where the next kept item goes. Rewrites arrays in place in one pass.

The idea

Both pointers start at the left. FAST walks every position; SLOW only moves when FAST finds something worth keeping, and that item is copied to SLOW's spot.

Everything before SLOW is the finished answer, so you never need a second array. This is how “remove duplicates”, “move zeroes” and “remove element” are solved in place.

The same idea with different speeds (one step vs two) finds the middle of a linked list or detects cycles.

See it step by step

Move zeroes to the end of [0, 1, 0, 3, 12]

  1. fast = 0 (0): skip. fast = 1 (1): write at slow = 0 → [1, 1, 0, 3, 12], slow = 1
  2. fast = 2 (0): skip. fast = 3 (3): write at 1 → [1, 3, 0, 3, 12], slow = 2
  3. fast = 4 (12): write at 2 → [1, 3, 12, 3, 12], slow = 3
  4. Fill positions 3… with 0 → [1, 3, 12, 0, 0].

In code (Python)

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

def remove_duplicates(sorted_nums):
    slow = 1
    for fast in range(1, len(sorted_nums)):
        if sorted_nums[fast] != sorted_nums[slow - 1]:
            sorted_nums[slow] = sorted_nums[fast]
            slow += 1
    return slow          # length of the de-duplicated prefix

print(move_zeroes([0, 1, 0, 3, 12]))        # [1, 3, 12, 0, 0]
print(remove_duplicates([1, 1, 2, 3, 3]))   # 3

O(n) time, O(1) space.

When you'll use it

  • “In place”, “without extra space”, removing or compacting items, partitioning.
  • Linked lists: middle node, cycle detection (fast moves two steps).

Common mistakes

  • Starting slow and fast at different places than the logic expects.
  • Forgetting the elements after SLOW still hold old values.

Practise it: Two Pointers

You'll use it again in

Go further