The problem asks to remove duplicates from a sorted array in-place, allowing each unique element to appear at most twice, and return the length of the resulting array. Since the array is sorted, duplicates are adjacent, and we need to ensure each element appears no more than twice in the final array.
The solution uses a two-pointer approach with a counter to track the frequency of each element, ensuring at most two occurrences are kept. Here’s how it operates:
j
to 1, indicating where the next valid element (within the allowed frequency) should be placed, since the first element is always included. A variable count
is set to 1 to track the frequency of the current element, starting with the first element.i
:
nums[i] == nums[i-1]
, the element is a duplicate, so we increment count
.nums[i] != nums[i-1]
, we’ve encountered a new element, so we reset count
to 1.count <= 2
, the current element is within the allowed frequency, so we place it at nums[j]
and increment j
. This ensures that each element appears at most twice in the output subarray.j
represents the length of the array with each element appearing at most twice, and the first j
elements of nums
contain the valid elements in sorted order. We return j
.count
variable ensures we include at most two occurrences of each element, and the j
pointer builds the result in-place, maintaining the relative order of elements.
The task is to modify a sorted array in-place such that each element appears at most twice, and return the new length of the array. Since the array is already sorted in non-decreasing order, any duplicates will be adjacent. The key challenge is to ensure that no value appears more than twice while preserving the relative order of valid elements, all without using extra space.
To solve this problem efficiently, we employ a two-pointer approach combined with a counter to track the number of times a particular value appears consecutively. We use a write pointer j
to track the position where the next valid element should be placed. The read pointer i
scans through the array, while a counter count
keeps track of how many times the current element has appeared so far.
We start by initializing j = 1
since the first element is always valid, and count = 1
for the first occurrence. Then, we iterate over the array from index 1 to the end:
nums[i] == nums[i - 1]
, we increment count
since it's a duplicate of the previous number.
nums[i] != nums[i - 1]
, we reset count
to 1 because we've encountered a new unique value.
count <= 2
, the current number is allowed to stay in the array (no more than twice). So, we place it at nums[j]
and increment j
.
This logic ensures that each unique number appears at most twice in the result. The elements are placed in the first j
positions of the array, forming the correct output in-place.
For input [1,1,1,2,2,3]
, the algorithm processes the first two 1s normally. When it sees the third 1, it skips it because count
becomes 3. It then processes the 2s similarly, keeping the first two and skipping any beyond that. The final array becomes [1,1,2,2,3]
, and the returned length is 5.
The solution has a linear time complexity of O(n), where n
is the length of the input array. Each element is visited exactly once. It also satisfies the space requirement of O(1) since it modifies the input array in-place without using any additional data structures.
This method leverages the fact that the array is sorted to efficiently manage duplicates by comparing each element with the one before it. The use of a counter ensures that we only accept up to two occurrences of any value. By using two pointers and tracking frequency, we maintain an optimized, readable, and space-efficient solution that aligns well with real-world in-place data cleaning tasks.