Bird
Raised Fist0
DSA C#programming

Remove Duplicates from Sorted Array Two Pointer in DSA C#

Choose your learning style10 modes available
Mental Model
Use two pointers to overwrite duplicates in a sorted array by keeping only unique elements at the front.
Analogy: Imagine sorting your books on a shelf and removing duplicate titles by sliding unique books forward to fill gaps left by duplicates.
[1, 1, 2, 3, 3, 4, 5]
 ↑  ↑
left right
Dry Run Walkthrough
Input: array: [1, 1, 2, 3, 3, 4, 5]
Goal: Remove duplicates so only unique elements remain at the start of the array
Step 1: Initialize left at index 0, right at index 1
[1, 1, 2, 3, 3, 4, 5]
 ↑left  ↑right
Why: Start comparing from the first two elements to find duplicates
Step 2: Compare values at left and right; both are 1, duplicate found, move right forward
[1, 1, 2, 3, 3, 4, 5]
 ↑left     ↑right
Why: Skip duplicate by moving right pointer to find next unique value
Step 3: Values differ (1 and 2), move left forward and overwrite left with right value (2)
[1, 2, 2, 3, 3, 4, 5]
    ↑left     ↑right
Why: Place unique value next to last unique and advance left pointer
Step 4: Move right forward to index 3, compare values at left (2) and right (3), different
[1, 2, 2, 3, 3, 4, 5]
       ↑left  ↑right
Why: Found next unique value, prepare to overwrite
Step 5: Move left forward and overwrite left with right value (3)
[1, 2, 3, 3, 3, 4, 5]
          ↑left  ↑right
Why: Keep unique values compacted at front
Step 6: Move right forward to index 4, values at left (3) and right (3) are same, duplicate found, move right forward
[1, 2, 3, 3, 3, 4, 5]
          ↑left     ↑right
Why: Skip duplicate by advancing right pointer
Step 7: Values at left (3) and right (4) differ, move left forward and overwrite left with right value (4)
[1, 2, 3, 4, 3, 4, 5]
             ↑left     ↑right
Why: Add next unique value to compacted front
Step 8: Move right forward to index 6, values at left (4) and right (5) differ, move left forward and overwrite left with right value (5)
[1, 2, 3, 4, 5, 4, 5]
                ↑left     ↑right
Why: Add last unique value
Result:
[1, 2, 3, 4, 5, 4, 5]
Unique count = 5
Annotated Code
DSA C#
using System;

class RemoveDuplicates {
    public static int RemoveDuplicatesFromSortedArray(int[] nums) {
        if (nums.Length == 0) return 0;
        int left = 0;
        for (int right = 1; right < nums.Length; right++) {
            if (nums[right] != nums[left]) {
                left++;
                nums[left] = nums[right];
            }
        }
        return left + 1;
    }

    static void Main() {
        int[] nums = {1, 1, 2, 3, 3, 4, 5};
        int uniqueCount = RemoveDuplicatesFromSortedArray(nums);
        for (int i = 0; i < uniqueCount; i++) {
            Console.Write(nums[i]);
            if (i < uniqueCount - 1) Console.Write(" -> ");
        }
        Console.WriteLine(" -> null");
        Console.WriteLine("Unique count = " + uniqueCount);
    }
}
if (nums.Length == 0) return 0;
handle empty array edge case
int left = 0;
initialize left pointer at start to track last unique element
for (int right = 1; right < nums.Length; right++) {
iterate right pointer through array to find unique elements
if (nums[right] != nums[left]) {
check if current right value is different from last unique
left++;
advance left pointer to next position for unique value
nums[left] = nums[right];
overwrite position after last unique with new unique value
return left + 1;
return count of unique elements found
OutputSuccess
1 -> 2 -> 3 -> 4 -> 5 -> null Unique count = 5
Complexity Analysis
Time: O(n) because we scan the array once with the right pointer
Space: O(1) because we modify the array in place without extra storage
vs Alternative: Compared to creating a new array for unique elements, this approach saves space by overwriting duplicates in place
Edge Cases
empty array
returns 0 immediately, no elements to process
DSA C#
if (nums.Length == 0) return 0;
array with all duplicates (e.g., [2,2,2])
returns 1, only one unique element remains at start
DSA C#
if (nums[right] != nums[left]) {
array with no duplicates (e.g., [1,2,3])
returns full length, array remains unchanged
DSA C#
if (nums[right] != nums[left]) {
When to Use This Pattern
When you see a sorted array and need to remove duplicates in place, use the two pointer pattern to compact unique elements efficiently.
Common Mistakes
Mistake: Not initializing left pointer correctly or starting right pointer at 0 causing incorrect comparisons
Fix: Start left at 0 and right at 1 to compare adjacent elements properly
Mistake: Not overwriting the array at left+1 position with the unique value found at right
Fix: Assign nums[left] = nums[right] after incrementing left pointer
Summary
Removes duplicates from a sorted array by overwriting duplicates with unique values using two pointers.
Use when you need to remove duplicates in place without extra space in a sorted array.
The key insight is to keep one pointer tracking the last unique element and the other scanning ahead for new unique values.

Practice

(1/5)
1. What is the main purpose of using two pointers in the Remove Duplicates from Sorted Array problem?
easy
A. To create a new array with unique elements
B. To sort the array before removing duplicates
C. To efficiently track unique elements and overwrite duplicates in-place
D. To count the total number of duplicates in the array

Solution

  1. Step 1: Understand the two-pointer approach

    One pointer tracks the position to place the next unique element, the other scans the array.
  2. Step 2: Purpose of pointers in-place

    This method avoids extra space by overwriting duplicates directly in the original array.
  3. Final Answer:

    To efficiently track unique elements and overwrite duplicates in-place -> Option C
  4. Quick Check:

    Two pointers help remove duplicates in-place [OK]
Hint: Two pointers track and overwrite duplicates without extra space [OK]
Common Mistakes:
  • Thinking two pointers sort the array
  • Assuming a new array is created
  • Confusing counting duplicates with removing them
2. Which of the following is the correct C# syntax to initialize the two pointers i and j for the problem?
easy
A. int i = 1; int j = 1;
B. int i = 1, j = 0;
C. int i = 0; int j = 0;
D. int i = 0, j = 1;

Solution

  1. Step 1: Identify pointer roles

    Pointer i starts at index 0 to track unique elements, j starts at 1 to scan ahead.
  2. Step 2: Check initialization correctness

    Initializing i = 0 and j = 1 matches the logic of comparing current and next elements.
  3. Final Answer:

    int i = 0, j = 1; -> Option D
  4. Quick Check:

    Start i at 0 and j at 1 [OK]
Hint: Start i at 0 and j at 1 to compare adjacent elements [OK]
Common Mistakes:
  • Starting both pointers at 0
  • Swapping i and j initialization
  • Starting both pointers at 1
3. What will be the output array and new length after running the two-pointer method on the sorted array [1, 1, 2, 3, 3]?
medium
A. [1, 2, 3, 3], length = 4
B. [1, 2, 3], length = 3
C. [1, 1, 2, 3, 3], length = 5
D. [1, 2, 2, 3], length = 4

Solution

  1. Step 1: Trace the two-pointer process

    Start with i=0, j=1. Compare elements: skip duplicates, overwrite unique elements at i+1.
  2. Step 2: Final array and length

    Unique elements are 1, 2, 3 placed at start. Length is 3.
  3. Final Answer:

    [1, 2, 3], length = 3 -> Option B
  4. Quick Check:

    Unique elements count = 3 [OK]
Hint: Overwrite duplicates, count unique elements for length [OK]
Common Mistakes:
  • Not updating length after removal
  • Leaving duplicates in output
  • Misplacing unique elements
4. Identify the error in the following C# code snippet for removing duplicates from a sorted array:
int RemoveDuplicates(int[] nums) {
    int i = 0, j = 1;
    while (j < nums.Length) {
        if (nums[i] != nums[j]) {
            i++;
            nums[i] = nums[j];
        }
        j++;
    }
    return i;
}
medium
A. The function should return i + 1 instead of i
B. Pointers i and j should both start at 1
C. The while loop condition should be j <= nums.Length
D. The array should be sorted inside the function

Solution

  1. Step 1: Understand pointer meaning

    Pointer i tracks last unique element index, so length is i + 1.
  2. Step 2: Check return value

    Returning i alone misses counting the first element, so return i + 1.
  3. Final Answer:

    The function should return i + 1 instead of i -> Option A
  4. Quick Check:

    Return length as i + 1 [OK]
Hint: Return i + 1 as length, not just i [OK]
Common Mistakes:
  • Returning i instead of i + 1
  • Incorrect loop boundary causing out-of-range
  • Sorting array inside function unnecessarily
5. Given a sorted array nums = [0,0,1,1,1,2,2,3,3,4], what will be the array state and returned length after applying the two-pointer duplicate removal method?
hard
A. [0, 1, 2, 3, 4], length = 5
B. [0, 0, 1, 2, 3, 4], length = 6
C. [0, 1, 1, 2, 3, 4], length = 6
D. [0, 1, 2, 3, 3, 4], length = 6

Solution

  1. Step 1: Apply two-pointer method step-by-step

    Start with i=0, j=1. Move j forward, overwrite duplicates by placing unique elements at i+1.
  2. Step 2: Final array and length

    Unique elements are 0,1,2,3,4 placed at start. Length is 5.
  3. Final Answer:

    [0, 1, 2, 3, 4], length = 5 -> Option A
  4. Quick Check:

    Unique count = 5 [OK]
Hint: Overwrite duplicates, count unique elements for final length [OK]
Common Mistakes:
  • Leaving duplicates in the array
  • Returning wrong length
  • Misplacing unique elements during overwrite
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard