🧠
Two Pointers with Count Tracking
💡 This approach introduces the two-pointer technique to efficiently track allowed duplicates while modifying the array in-place, improving performance drastically.
Intuition
Use one pointer to iterate over the array and another to build the result. Keep track of how many times the current number has appeared and only copy it if it appears at most twice.
Algorithm
- Initialize two pointers: write_index at 0 and read_index at 0.
- Initialize count to 1 for the first element.
- Iterate read_index through the array starting from 1.
- If current element equals previous, increment count; else reset count to 1.
- If count ≤ 2, copy current element to write_index and increment write_index.
- Return write_index as the new length.
💡 Tracking count and using two pointers avoids shifting and keeps the array modified in-place efficiently.
def remove_duplicates(nums):
if len(nums) <= 2:
return len(nums)
write_index = 1
count = 1
for read_index in range(1, len(nums)):
if nums[read_index] == nums[read_index - 1]:
count += 1
else:
count = 1
if count <= 2:
nums[write_index] = nums[read_index]
write_index += 1
return write_index
# Driver code
if __name__ == '__main__':
arr = [1,1,1,2,2,3]
length = remove_duplicates(arr)
print(length) # Expected: 5
print(arr[:length]) # Expected: [1,1,2,2,3]
Line Notes
if len(nums) <= 2Handle small arrays where no removal is needed
write_index = 1Position to write next allowed element
count = 1Count occurrences of current element
for read_index in range(1, len(nums))Traverse array from second element
if nums[read_index] == nums[read_index - 1]Check if current equals previous to count duplicates
count += 1Increment count for duplicate
else: count = 1Reset count for new element
if count <= 2Allow up to two duplicates
nums[write_index] = nums[read_index]Copy allowed element to write_index
write_index += 1Move write pointer forward
public class Solution {
public static int removeDuplicates(int[] nums) {
if (nums.length <= 2) return nums.length;
int writeIndex = 1, count = 1;
for (int readIndex = 1; readIndex < nums.length; readIndex++) {
if (nums[readIndex] == nums[readIndex - 1]) {
count++;
} else {
count = 1;
}
if (count <= 2) {
nums[writeIndex] = nums[readIndex];
writeIndex++;
}
}
return writeIndex;
}
public static void main(String[] args) {
int[] arr = {1,1,1,2,2,3};
int length = removeDuplicates(arr);
System.out.println(length); // Expected: 5
for (int i = 0; i < length; i++) {
System.out.print(arr[i] + " ");
}
}
}
Line Notes
if (nums.length <= 2)Handle trivial cases quickly
int writeIndex = 1, count = 1Initialize write pointer and count
for (int readIndex = 1; readIndex < nums.length; readIndex++)Traverse array from second element
if (nums[readIndex] == nums[readIndex - 1])Check for duplicate
count++Increment duplicate count
else { count = 1; }Reset count for new element
if (count <= 2)Allow up to two duplicates
nums[writeIndex] = nums[readIndex]Overwrite element at writeIndex
writeIndex++Advance write pointer
#include <iostream>
#include <vector>
using namespace std;
int removeDuplicates(vector<int>& nums) {
if (nums.size() <= 2) return nums.size();
int writeIndex = 1, count = 1;
for (int readIndex = 1; readIndex < nums.size(); readIndex++) {
if (nums[readIndex] == nums[readIndex - 1]) {
count++;
} else {
count = 1;
}
if (count <= 2) {
nums[writeIndex] = nums[readIndex];
writeIndex++;
}
}
return writeIndex;
}
int main() {
vector<int> arr = {1,1,1,2,2,3};
int length = removeDuplicates(arr);
cout << length << endl; // Expected: 5
for (int i = 0; i < length; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
Line Notes
if (nums.size() <= 2)Quickly return for small arrays
int writeIndex = 1, count = 1Initialize pointers and count
for (int readIndex = 1; readIndex < nums.size(); readIndex++)Traverse array from second element
if (nums[readIndex] == nums[readIndex - 1])Check for duplicate
count++Increment count for duplicate
else { count = 1; }Reset count for new element
if (count <= 2)Allow up to two duplicates
nums[writeIndex] = nums[readIndex]Overwrite element at writeIndex
writeIndex++Advance write pointer
function removeDuplicates(nums) {
if (nums.length <= 2) return nums.length;
let writeIndex = 1, count = 1;
for (let readIndex = 1; readIndex < nums.length; readIndex++) {
if (nums[readIndex] === nums[readIndex - 1]) {
count++;
} else {
count = 1;
}
if (count <= 2) {
nums[writeIndex] = nums[readIndex];
writeIndex++;
}
}
return writeIndex;
}
// Test
const arr = [1,1,1,2,2,3];
const length = removeDuplicates(arr);
console.log(length); // Expected: 5
console.log(arr.slice(0, length)); // Expected: [1,1,2,2,3]
Line Notes
if (nums.length <= 2) return nums.lengthHandle small arrays quickly
let writeIndex = 1, count = 1Initialize pointers and count
for (let readIndex = 1; readIndex < nums.length; readIndex++)Traverse array from second element
if (nums[readIndex] === nums[readIndex - 1])Check for duplicate
count++Increment count for duplicate
else { count = 1; }Reset count for new element
if (count <= 2)Allow up to two duplicates
nums[writeIndex] = nums[readIndex]Overwrite element at writeIndex
writeIndex++Advance write pointer
Single pass through the array with constant extra space.
💡 For n=20, this means about 20 operations, which is very efficient.
Interview Verdict: Accepted / Optimal for interview coding
This approach is efficient and easy to implement, making it ideal for interviews.