26. Remove Duplicates From Sorted Array - Explanation

Problem Link

Description

You are given an integer array nums sorted in non-decreasing order. Your task is to remove duplicates from nums in-place so that each element appears only once.

After removing the duplicates, return the number of unique elements, denoted as k, such that the first k elements of nums contain the unique elements.

Note:

  • The order of the unique elements should remain the same as in the original array.
  • It is not necessary to consider elements beyond the first k positions of the array.
  • To be accepted, the first k elements of nums must contain all the unique elements.

Return k as the final result.

Example 1:

Input: nums = [1,1,2,3,4]

Output: [1,2,3,4]

Explanation: You should return k = 4 as we have four unique elements.

Example 2:

Input: nums = [2,10,10,30,30,30]

Output: [2,10,30]

Explanation: You should return k = 3 as we have three unique elements.

Constraints:

  • 1 <= nums.length <= 30,000
  • -100 <= nums[i] <= 100
  • nums is sorted in non-decreasing order.


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Two Pointers - Using a read pointer and write pointer to modify arrays in-place
  • In-Place Array Modification - Overwriting elements without using extra space
  • Sorted Array Properties - Understanding that duplicates are always adjacent in sorted arrays

1. Sorted Set

Intuition

A set automatically removes duplicates, and a sorted set maintains order. We insert all elements into a sorted set, then copy the unique elements back to the original array. This approach is simple but uses extra space and doesn't take advantage of the array already being sorted.

Algorithm

  1. Insert all elements from the array into a sorted set to eliminate duplicates.
  2. Copy the unique elements from the set back into the beginning of the original array.
  3. Return the size of the set (number of unique elements).

Note: This approach is simple but uses extra O(n) space.

class Solution:
    def removeDuplicates(self, nums: list[int]) -> int:
        unique = sorted(set(nums))
        nums[:len(unique)] = unique
        return len(unique)

Time & Space Complexity

  • Time complexity: O(nlogn)O(n \log n)
  • Space complexity: O(n)O(n)

2. Two Pointers - I

Intuition

Since the array is sorted, duplicates are adjacent. We use two pointers: one (l) marks where to place the next unique element, and another (r) scans through the array. When r finds a new value (different from what's at l), we copy it to position l and advance both pointers. This modifies the array in-place.

Algorithm

  1. Initialize both pointers l and r to 0.
  2. Copy the current element at r to position l.
  3. Skip all duplicates by advancing r while consecutive elements are equal.
  4. Move l forward to prepare for the next unique element.
  5. Return l as the count of unique elements.
class Solution:
    def removeDuplicates(self, nums: list[int]) -> int:
        n = len(nums)
        l = r = 0
        while r < n:
            nums[l] = nums[r]
            while r < n and nums[r] == nums[l]:
                r += 1
            l += 1
        return l

Time & Space Complexity

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

3. Two Pointers - II

Intuition

A more elegant approach: we compare each element with its predecessor. Since duplicates are consecutive in a sorted array, an element is unique if it differs from the one before it. We maintain a write pointer that only advances when we find a new unique value.

Algorithm

  1. Start with l = 1 since the first element is always unique.
  2. Iterate r from 1 to the end of the array.
  3. If nums[r] differs from nums[r - 1], it's a new unique value.
  4. Copy it to position l and increment l.
  5. Return l as the count of unique elements.
class Solution:
    def removeDuplicates(self, nums: list[int]) -> int:
        l = 1
        for r in range(1, len(nums)):
            if nums[r] != nums[r - 1]:
                nums[l] = nums[r]
                l += 1
        return l

Time & Space Complexity

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

Common Pitfalls

Not Leveraging the Sorted Property

The array is already sorted, meaning duplicates are always adjacent. Some solutions use a hash set or sort the array again, which wastes time and space. Since duplicates are consecutive, you only need to compare each element with its predecessor (or the last written element) to detect duplicates in O(1) space.

Returning the Wrong Value

The function should return the count of unique elements, not modify and return the array itself. Additionally, the returned length k means the first k elements of nums contain the unique values. Some solutions off-by-one error by returning l - 1 instead of l, or forget that the write pointer already represents the count of unique elements written.