Remove Duplicates from Sorted Array II
Remove Duplicates from Sorted Array II
Given a sorted integer slice, remove duplicates in-place so that each value appears at most twice. Return the new length k such that the first k elements contain the allowed values in sorted order.
Function signature
func RemoveDuplicatesSortedArrayII(nums []int) int
Inputs / outputs
nums: sorted slice to modify in-place.- Return: number of kept elements
k; onlynums[:k]is valid after the call.
Example
nums = [1,1,1,2,2,3]
After removal: nums = [1,1,2,2,3,_]
Return k = 5
Constraints
0 <= len(nums) <= 100_000-1_000_000_000 <= nums[i] <= 1_000_000_000
Core idea (near-solution)
Because the array is sorted, any value beyond the second occurrence can be skipped. The easiest invariant uses the write index:
Invariant: nums[:write] contains the valid output so far, with no value appearing more than twice.
If write < 2, you can always keep the element. Otherwise, compare nums[read] to nums[write-2]:
- If they are different, the current value has appeared fewer than twice in the output, so keep it.
- If they are the same, this would be a third occurrence - skip it.
Algorithm (step-by-step)
- If
len(nums) <= 2, returnlen(nums). - Set
write = 2. - For
readfrom2tolen(nums)-1:- If
nums[read] != nums[write-2], setnums[write] = nums[read]and incrementwrite.
- If
- Return
write.
Correctness sketch
- Invariant:
nums[:write]contains the valid output so far, with no value appearing more than twice. - Each step moves at least one pointer, shrinking the remaining search space.
- The invariant ensures elements outside the active window are already handled correctly.
- When pointers meet or cross, all candidates have been considered.
Trace (hand walkthrough)
Trace Walkthrough
Example input:
nums = [1,1,1,2,2,3]
After removal: nums = [1,1,2,2,3,_]
Return k = 5
Walk:
- start with first two kept: [1,1], write=2
- i=2 val=1, compare nums[write-2]=1 -> skip (would make 3 copies)
- i=3 val=2, compare nums[0]=1 -> keep -> nums[2]=2, write=3
- i=4 val=2, compare nums[1]=1 -> keep -> nums[3]=2, write=4
- i=5 val=3, compare nums[2]=2 -> keep -> nums[4]=3, write=5 => [1,1,2,2,3]
Pitfalls to avoid
- Using the wrong comparison index (the
write-2check is key). - Failing to handle arrays of length 0, 1, or 2.
- Returning a new slice instead of the new length.
Complexity
- Time:
O(n) - Extra space:
O(1)
Implementation notes (Go)
- This approach preserves order and is stable.
Run tests to see results
No issues detected