LeetCode #26 Easy

Remove Duplicates from Sorted Array

Given a sorted array, remove duplicates in place so each value appears once. Return the new length k; the first k slots must hold the unique values.

Constraints
  • 1 <= nums.length <= 3 * 10⁴
  • -100 <= nums[i] <= 100
  • nums is sorted in non-decreasing order.
arraytwo-pointers
Open on LeetCode ↗
02

Intuition

Remove duplicates from sorted array removes duplicates in place, returning the count of unique elements. The array is sorted, so duplicates are always adjacent — which is what makes a single pass possible. The problem's contract is worth reading carefully. It asks for the count, and only requires the first k positions to hold the unique values. Whatever sits beyond position k is ignored, so nothing needs shifting, erasing, or resizing. That frees the solution to use two pointers with different roles: - A write pointer marks where the next unique value belongs, while a read pointer scans forward looking for values not yet written. The write pointer starts at 1, since the first element is always unique and already in place. For each element, compare against the value at write − 1 — the last unique value written. If they differ, write it and advance. Comparing against nums[write − 1] rather than nums[read − 1] is the detail that matters. The last written value is the correct reference, and comparing with the previous read position breaks once the two pointers diverge. The write pointer's final value is the count, which is exactly what the function returns. An empty array returns 0, and a single element returns 1 — both fall out if the write pointer starts at 1 and the loop begins at index 1, since the loop simply does not run. Remove Duplicates from Sorted Array II allows each value twice, and adapts by comparing against nums[write − 2] instead. One pass with two indices gives O(n) time and O(1) space.

How to spot this pattern

The read/write two-pointer: one index scans every element, a slower one marks where the next kept value goes. Because the array is sorted, duplicates are adjacent and a single comparison against the last kept value decides. Any in-place "remove or compact" problem uses this same slow-write, fast-read split.

03

Approach

Try it first

Before reading on: price up what the brute force costs here, then ask what makes it safe to discard one end without checking it against everything. Aim for O(n) time and O(1) space.

1

Use the sorted order

Duplicates are always adjacent in sorted data, so a single forward pass can detect every one without a set or extra structure.

2

Read the contract

Only the count and the first k positions matter. Whatever lies beyond position k is ignored, so no shifting or resizing is required.

3

Separate read and write pointers

The write pointer marks where the next unique value belongs; the read pointer scans ahead. They advance at different rates.

4

Start writing at index 1

The first element is always unique and already correctly placed, so the write pointer begins at 1 and the scan at index 1.

5

Compare against the last written

Test nums[read] != nums[write - 1]. Comparing with the previous read position breaks once the pointers diverge — the last written value is the right reference.

6

Return the write pointer

Its final value is the count of unique elements, which is what the function returns. Empty and single-element arrays work with no special case.

7

Cost of the approach

One pass with two indices gives O(n) time and O(1) space, modifying the array in place as required.

04

Solution & live demo

▶1class Solution:
▶2 def removeDuplicates(self, nums):
▶3 l = 0
▶4 for k in range(1, len(nums)):
▶5 if nums[k] != nums[l]:
▶6 l += 1
▶7 nums[l] = nums[k]
▶8 return l + 1
05

Common pitfalls

Comparing against the previous scanned element

✗ Wrong
if nums[k] != nums[k - 1]:
✓ Right
if nums[k] != nums[l]:

It happens to work on sorted input, but the meaningful comparison is against the last kept value — nums[l] — which is what generalises to variants like "allow at most two duplicates". Comparing to k - 1 reads a slot that may already have been overwritten.

Incrementing the write pointer before writing

✗ Wrong
nums[l] = nums[k]
l += 1
✓ Right
l += 1
nums[l] = nums[k]

l points at the last kept element, not at the next free slot, so writing before advancing overwrites a value you meant to keep. Advance to the empty position, then store.

Returning l instead of l + 1

✗ Wrong
return l
✓ Right
return l + 1

l is an index; the problem wants a count. With one distinct element l is 0 but the length is 1.

06

Edge cases

No duplicates at all

Every nums[k] differs, so l advances each step and the whole array is kept.

All identical values

No nums[k] differs from nums[l]; l stays 0 and length 1 is returned.

Single element

The loop never runs; l + 1 = 1 is correct.

07

Complexity

Time
O(n)
Space
O(1)
Single pass with a read and a write pointer.