← All Foundations

Two Pointers

Foundation drill for this topic

Drill #126 — Remove Duplicates from Sorted Array

Easy Slow-Fast Write

In plain English: Remove duplicate values from a sorted list in-place and return how many unique values remain.

Slow pointer marks the write position, fast pointer scans ahead. When fast finds a new value, write it at slow+1 and advance slow. The sorted order guarantees duplicates are adjacent.

Prompt

Given a sorted array nums, remove the duplicates in-place such that each element appears only once. Return the new length.

Try to write it from scratch before scrolling down.

Solution

def remove_duplicates(nums):
    if not nums:
        return 0
    slow = 0  # slow = next write position for a unique value
    for fast in range(1, len(nums)):  # fast scans ahead for new values
        if nums[fast] != nums[slow]:
            slow += 1
            nums[slow] = nums[fast]
    return slow + 1

# Test: nums = [1,1,2]; remove_duplicates(nums) == 2; nums[:2] == [1,2]
# Test: nums = [0,0,1,1,1,2,2,3,3,4]
#       remove_duplicates(nums) == 5; nums[:5] == [0,1,2,3,4]
O(n) time · O(1) space

Related Micro Drills

Quick recall drills to reinforce this pattern.

8 Remove duplicates (sorted array) Pointer Manipulation 10s

Two-pointer write keeps unique elements in-place with O(1) space. Core array cleanup technique.

# Two-pointer write — keep unique in-place
w = 1
for r in range(1, len(a)):
    if a[r] != a[r - 1]:
        a[w] = a[r]
        w += 1
# a[:w] has unique elements
126 Remove duplicates in-place Pointer Manipulation 10s

Write-pointer compaction for sorted arrays. Returns new length.

w = 1
for i in range(1, len(a)):
    if a[i] != a[i-1]:
        a[w] = a[i]
        w += 1
return w
87 Move zeros to end Pointer Manipulation 10s

Move-zeroes is remove-element followed by a fill. Classic two-pointer warm-up.

w = 0
for r in range(len(a)):
    if a[r] != 0:
        a[w] = a[r]
        w += 1
while w < len(a):
    a[w] = 0
    w += 1
See all drills in Two Pointers →