CLOSE
🛠️ Settings

Problem Statement

Given an integer array nums sorted 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 are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.

Return k after placing the final result in the first k slots of nums.

Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.

Links

Remove duplicates from sorted array 2

Constraints

1 <= nums.length <= 3 * 10^4
-104 <= nums[i] <= 104
nums is sorted in non-decreasing order.

Examples

Example 1:

Input: nums = [1,1,1,2,2,3]
Output: 5, nums = [1,1,2,2,3,_]

Explanation: Your function should return k = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).

Example 2:

Input: nums = [0,0,1,1,1,1,2,3,3]
Output: 7, nums = [0,0,1,1,2,3,3,_,_]

Explanation: Your function should return k = 7, with the first seven elements of nums being 0, 0, 1, 1, 2, 3 and 3 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).

Different Approaches

1️⃣ Two Pointers

Intuition:

Since the array is sorted, duplicates appear next to each other.

We need to keep at most two occurrences of each element.

Use a Two Pointer Pointers approach:

  • Pointer i will track the position to insert the next valid element.
  • Pointer j will iterate through the array.

We allow the first two elements always, From index 2 onwards, if nums[j] != nums[i-2], it's valid to keep it.

Dry Run:

Initialization:

i = 2

Start Iterating from j = 2 to n - 1

i = 2
j = 2 (loop)
       +-----+-----+-----+-----+-----+-----+
nums = |  1  |  1  |  1  |  2  |  2  |  3  |
       +-----+-----+-----+-----+-----+-----+
          0     1     2     3     4     5
                      ^
                      |
                      i
                      j

    Compare nums[j] with nums[i-2]
    If nums[j] == nums[i-2]
       nums[2] == nums[0]
       1 == 1
       ❌ Skip (this is the 3rd occurrence of 1)
i = 2
j = 3 (loop)
       +-----+-----+-----+-----+-----+-----+
nums = |  1  |  1  |  1  |  2  |  2  |  3  |
       +-----+-----+-----+-----+-----+-----+
          0     1     2     3     4     5
                      ^     ^
                      |     |
                      i     j

    Compare nums[j] with nums[i-2]
    If nums[j] == nums[i-2]
       nums[3] == nums[0]
            2 == 1
            False
       Set nums[i] = nums[j]
           nums[2] = 2
           i++ -> i = 3
i = 3
j = 4 (loop)
       +-----+-----+-----+-----+-----+-----+
nums = |  1  |  1  |  2  |  2  |  2  |  3  |
       +-----+-----+-----+-----+-----+-----+
          0     1     2     3     4     5
                            ^     ^
                            |     |
                            i     j

    Compare nums[j] with nums[i-2]
    If nums[j] == nums[i-2]
       nums[4] == nums[1]
            2 == 1
            False
       Set nums[i] = nums[j]
           nums[3] = 2
           i++ -> i = 4
i = 4
j = 5 (loop)
       +-----+-----+-----+-----+-----+-----+
nums = |  1  |  1  |  2  |  2  |  2  |  3  |
       +-----+-----+-----+-----+-----+-----+
          0     1     2     3     4     5
                                  ^     ^
                                  |     |
                                  i     j

    Compare nums[j] with nums[i-2]
    If nums[j] == nums[i-2]
       nums[4] == nums[2]
            3 == 2
            False
       Set nums[i] = nums[j]
           nums[4] = 3
           i++ -> i = 5

Out of bounds:

Final State:

i = 5
j = 6 (loop) (out of bounds)
       +-----+-----+-----+-----+-----+-----+
nums = |  1  |  1  |  2  |  2  |  3  |  3  |
       +-----+-----+-----+-----+-----+-----+
          0     1     2     3     4     5
                                        ^     ^
                                        |     |
                                        i     j
i points to the position just after the last valid element. Since arrays are zero-indexed, this means the first i elements are valid.

Code:

int removeDuplicates(vector<int>& nums) {
    int n = nums.size(); // Get the size of the input array

    // If the array has 2 or fewer elements, it already meets the condition
    if (n <= 2) return n;

    int i = 2;  // Start placing elements from the 3rd position (index 2)

    // Loop through the array starting from the 3rd element
    for (int j = 2; j < n; ++j) {
        // Compare current element with the element at position i-2
        // This checks if the current element is allowed (i.e., not more than twice)
        if (nums[j] != nums[i - 2]) {
            // If not equal, it's safe to include the current number
            nums[i] = nums[j]; // Place the number at the current write index
            ++i; // Move the write index forward
        }
        // If it *is* equal, it means we've already included two of these, so skip it
    }

    // After the loop, i represents the new length of the modified array
    return i;
}

Complexity Analysis:

  • Time Complexity:O(n)
  • Space Complexity:O(1)