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.
- 1 <= nums.length <= 3 * 10⁴
- -100 <= nums[i] <= 100
- nums is sorted in non-decreasing order.
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.
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.
Approach
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.
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.
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.
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.
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.
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.
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.
Cost of the approach
One pass with two indices gives O(n) time and O(1) space, modifying the array in place as required.
Solution & live demo
Common pitfalls
Comparing against the previous scanned element
if nums[k] != nums[k - 1]:
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
nums[l] = nums[k] l += 1
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
return l
return l + 1
l is an index; the problem wants a count. With one distinct element l is 0 but the length is 1.
Edge cases
Every nums[k] differs, so l advances each step and the whole array is kept.
No nums[k] differs from nums[l]; l stays 0 and length 1 is returned.
The loop never runs; l + 1 = 1 is correct.