Remove Duplicates from Sorted Array
Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once. The relative order of the elements should be kept the same. Then return the number of unique elements in nums. Consider the number of unique elements of nums to be k. To get accepted, you need to do the following: Change the array nums such that the first k elements of nums contain the unique elements in the order they were present in nums originally. The remaining elements of nums as well as the size of nums do not matter. Return k.
- 1 <= nums.length <= 3 * 10^4
- -100 <= nums[i] <= 100
- nums is sorted in non-decreasing order
- Solve in-place with O(1) extra memory
nums = [1,1,2]2, nums = [1,2,_]nums = [0,0,1,1,1,2,2,3,3,4]5, nums = [0,1,2,3,4,_,_,_,_,_]nums = [1]1, nums = [1]If we have a sorted list of items, we are fully guaranteed that identical numbers will always be sitting right next to each other. Our goal is to extract only the unique items, moving them to the front of the list.
The most obvious approach is to just delete a number whenever you see a duplicate. But behind the scenes, deleting an item from an array forces the computer to physically shift every single remaining item to the left to fill the gap. If we have to shift items for every duplicate, the process becomes incredibly slow.
for i in range(len(nums) - 1, 0, -1):
if nums[i] == nums[i-1]:
nums.pop(i) # Super slow! Shifts everything left.To avoid deleting items and causing massive shifting, this is the perfect job for the Two-Pointer Pattern. This pattern is wildly important because it lets us compress the array "in-place", meaning we overwrite bad items instead of deleting them. We use two pointers moving from left to right:
- The Collector (Slow): Keeps track of where the next unique number should be saved.
- The Explorer (Fast): Runs ahead looking for completely new numbers.
The Explorer checks every single number. It compares what it's currently looking at with the last unique number we collected. If they are exactly the same, it's a duplicate, so we just ignore it. But if it's different, the Explorer found a brand new number! We copy it into the Collector's spot and push the Collector forward.
if not nums: return 0
collector = 1
for explorer in range(1, len(nums)):
if nums[explorer] != nums[collector - 1]:
nums[collector] = nums[explorer]
collector += 1
return collectorIn-Place De-Duplication
Collector & Scout Pointers
Key Insight
The Slow pointer acts as a gatekeeper, storing unique sorted elements. The Fast pointer scouts ahead. When a new value is found, we extend the unique sequence.
In-Place Efficiency
By modifying the array directly, we achieve O(1) space complexity. We overwrite duplicates with new unique values, so we don't need extra memory.