0080. Remove Duplicates from Sorted Array II¶
Table of Contents¶
- Problem
- Problem Breakdown
- Approach 1: Two Pointers (Generic, At-Most-K)
- Approach 2: Two Pointers (Specialized for K=2)
- Complexity Comparison
- Edge Cases
- Common Mistakes
- Related Problems
- Visual Animation
Problem¶
| Leetcode | 80. Remove Duplicates from Sorted Array II |
| Difficulty | |
| Tags | Array, Two Pointers |
Description¶
Given an integer array
numssorted in non-decreasing order, remove some duplicates in-place such that each unique element appears at most twice. The relative order of the elements should be kept the same.Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array
nums. More formally, if there arekelements after removing the duplicates, then the firstkelements ofnumsshould hold the final result. It does not matter what you leave beyond the firstkelements.Return
kafter placing the final result in the firstkslots ofnums.
Examples¶
Example 1:
Input: nums = [1,1,1,2,2,3]
Output: 5, nums = [1,1,2,2,3,_]
Example 2:
Input: nums = [0,0,1,1,1,1,2,3,3]
Output: 7, nums = [0,0,1,1,2,3,3,_,_]
Constraints¶
1 <= nums.length <= 3 * 10^4-10^4 <= nums[i] <= 10^4numsis sorted in non-decreasing order.
Problem Breakdown¶
1. What is being asked?¶
Compact the array so each value appears at most twice, in-place, preserving order.
2. What is the input?¶
| Parameter | Type | Description |
|---|---|---|
nums | int[] | Sorted ascending |
3. What is the output?¶
The length k of the compacted prefix.
4. Constraints analysis¶
| Constraint | Significance |
|---|---|
| Sorted | Duplicates are adjacent |
n <= 3 * 10^4 | O(n) easy |
5. Step-by-step example analysis¶
[1, 1, 1, 2, 2, 3]¶
Two-pointer trick: write index `i` (starts at 2 โ keep first 2 always).
For each j = 2..n-1:
If nums[j] != nums[i - 2]: nums[i] = nums[j]; i++.
Else: skip (would create a 3rd consecutive copy).
Walk:
i = 2 (kept [1,1])
j=2: nums[j]=1, nums[i-2]=1 โ skip. i=2.
j=3: nums[j]=2, nums[i-2]=1 โ write. nums=[1,1,2,2,2,3], i=3.
j=4: nums[j]=2, nums[i-2]=1 โ write. nums=[1,1,2,2,2,3], i=4.
j=5: nums[j]=3, nums[i-2]=2 โ write. nums=[1,1,2,2,3,3], i=5.
Return 5.
6. Key Observations¶
- At-most-2 invariant -- We allow
nums[i] == nums[i-1] == nums[i-2]to be impossible by checking the new value againstnums[i-2]. - Generalizes to "at most k" -- Replace the
2withk: write index starts atk, compare withnums[i-k].
7. Pattern identification¶
| Pattern | Why it fits |
|---|---|
| Two pointers | Read pointer + write pointer, classic compaction |
Chosen pattern: Two Pointers (At-Most-K).
Approach 1: Two Pointers (Generic, At-Most-K)¶
Algorithm¶
- If
len(nums) <= k, returnlen(nums). i = k(firstkalways kept).- For
j = k..n-1: - If
nums[j] != nums[i - k]:nums[i] = nums[j]; i++. - Return
i.
Complexity¶
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(1) |
Implementation (k = 2)¶
Go¶
func removeDuplicates(nums []int) int {
k := 2
if len(nums) <= k {
return len(nums)
}
i := k
for j := k; j < len(nums); j++ {
if nums[j] != nums[i-k] {
nums[i] = nums[j]
i++
}
}
return i
}
Java¶
class Solution {
public int removeDuplicates(int[] nums) {
int k = 2;
if (nums.length <= k) return nums.length;
int i = k;
for (int j = k; j < nums.length; j++) {
if (nums[j] != nums[i - k]) {
nums[i] = nums[j];
i++;
}
}
return i;
}
}
Python¶
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
k = 2
if len(nums) <= k: return len(nums)
i = k
for j in range(k, len(nums)):
if nums[j] != nums[i - k]:
nums[i] = nums[j]
i += 1
return i
Dry Run¶
nums = [0,0,1,1,1,1,2,3,3]
k = 2
Initial: keep first 2 โ [0, 0, ...], i = 2
j=2: nums[2]=1, nums[i-2]=0 โ write 1; i=3 โ nums=[0,0,1,1,1,1,2,3,3]
j=3: nums[3]=1, nums[i-2]=0 โ write 1; i=4 โ nums=[0,0,1,1,1,1,2,3,3]
j=4: nums[4]=1, nums[i-2]=1 โ skip
j=5: nums[5]=1, nums[i-2]=1 โ skip
j=6: nums[6]=2, nums[i-2]=1 โ write; i=5 โ nums=[0,0,1,1,2,1,2,3,3]
j=7: nums[7]=3, nums[i-2]=1 โ write; i=6 โ nums=[0,0,1,1,2,3,2,3,3]
j=8: nums[8]=3, nums[i-2]=2 โ write; i=7 โ nums=[0,0,1,1,2,3,3,3,3]
Return i = 7. First 7 elements: [0,0,1,1,2,3,3].
Approach 2: Two Pointers (Specialized for K=2)¶
Idea¶
Same algorithm, hard-coded for
k = 2.Listed for clarity; identical performance.
Complexity Comparison¶
| # | Approach | Time | Space | Pros | Cons |
|---|---|---|---|---|---|
| 1 | Generic K | O(n) | O(1) | Generalizes | -- |
| 2 | Specialized | O(n) | O(1) | Slightly fewer ops | Less reusable |
Which solution to choose?¶
Approach 1 always.
Edge Cases¶
| # | Case | Reason |
|---|---|---|
| 1 | n <= 2 | Already valid |
| 2 | All same | Keep two |
| 3 | All distinct | Unchanged |
| 4 | Twos only | Keep first two of each value |
| 5 | Long runs | Compact each run |
Common Mistakes¶
Mistake 1: Comparing with nums[i - 1] instead of nums[i - k]¶
# WRONG โ keeps only 1 copy of each (this is Problem 26)
if nums[j] != nums[i - 1]: ...
# CORRECT โ for at-most-2, compare with i-2
if nums[j] != nums[i - 2]: ...
Mistake 2: Starting i at 0 or 1¶
Related Problems¶
| # | Problem | Difficulty | Similarity |
|---|---|---|---|
| 1 | 26. Remove Duplicates from Sorted Array | At-most-1 version | |
| 2 | 27. Remove Element | Two-pointer compaction | |
| 3 | 283. Move Zeroes | Same compact pattern |
Visual Animation¶
Interactive animation: animation.html
The animation includes: - Two pointers
i,jwalking the array - Highlight comparisons withnums[i-2]- Step-by-step writes