Editorial
Core insight
Remove Duplicates from Sorted Array · Two Pointers
Core Insight for Remove Duplicates from Sorted Array
The key intuition for LeetCode 26 Solution lies in the fact that the array is sorted. This guarantees that all duplicate values are adjacent to each other. We do not need a hash set to track seen elements; we only need to compare the current element with the previous one.
The optimal strategy decouples the "reading" of data from the "writing" of data.
- Read Pointer (
fast): Scans the array from left to right. - Write Pointer (
slow): Indicates the position where the next unique element should be placed.
Invariant:
At any point in the execution, the subarray nums[0...slow-1] contains exactly the unique elements found so far, in sorted order. The fast pointer searches for a value strictly greater than the last unique value found. When fast finds a new unique number, we copy it to the slow position and advance slow.
Visual Description:
Imagine the array is divided into two regions. The left region (indices 0 to slow-1) is the "processed/unique" zone. The right region is the "unknown/unprocessed" zone. The fast pointer expands the known territory. Since fast is always equal to or ahead of slow, we can safely overwrite nums[slow] because its original value has already been processed or is a duplicate we no longer need.

Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 26: Remove Duplicates from Sorted Array Solution & Explanation
Problem Overview
TL;DR: Use a "slow" pointer to track the position of the last unique element and a "fast" pointer to scan the array, overwriting duplicates in-place.
The LeetCode 26 problem, Remove Duplicates from Sorted Array, asks us to process a sorted integer array and modify it directly so that every element appears only once. Because the array is sorted, duplicates are grouped together. We must place the unique elements at the beginning of the array and return the count of these unique elements. This is a classic interview question testing mastery of array manipulation and space efficiency.
Brute Force Approach for Remove Duplicates from Sorted Array
A naive approach to solving this problem in-place involves simulating the deletion process manually. When we iterate through the array and find a duplicate (where nums[i] == nums[i-1]), we can shift all subsequent elements one position to the left to overwrite the duplicate.
Pseudo-code:
function removeDuplicates(nums):
i = 1
current_length = nums.length
while i < current_length:
if nums[i] == nums[i-1]:
# Shift all elements from i to end one step left
for j from i to current_length - 2:
nums[j] = nums[j+1]
current_length = current_length - 1
else:
i = i + 1
return current_lengthTime Complexity: Space Complexity:
Why this fails: While this solution respects the space constraint, it fails on time efficiency. For every duplicate found, we perform a shift operation that takes time. In the worst-case scenario (an array with all unique elements or many duplicates), this results in quadratic time complexity. For an input size of , an operation performs roughly operations, which risks a Time Limit Exceeded (TLE) error or simply performs poorly compared to the optimal linear solution.
Algorithm Strategy: Two Pointer Patterns
- Initialization: We know the first element (
index 0) is always unique because there is no element before it. Therefore, we initialize ourslowpointer (write index) at1. We also start ourfastpointer (read index) at1. - Iteration: We iterate the
fastpointer through the array until it reaches the end. - Comparison: At each step, we compare the element at
nums[fast]withnums[fast - 1].- If
nums[fast]is different fromnums[fast - 1], it indicates a new unique element has been found. - If they are the same, it is a duplicate and should be ignored.
- If
- Modification: When a unique element is found:
- Copy the value
nums[fast]tonums[slow]. - Increment
slowto prepare for the next unique element.
- Copy the value
- Termination: Once
fasthas scanned the entire array, the value ofslowrepresents the count of unique elements. The firstslowelements of the array are now the unique set.
Execution Flow
Consider the input: nums = [0, 0, 1, 1, 1, 2, 2]
- Start:
slow = 1,fast = 1. - Step 1 (
fast = 1): Comparenums[1](0) withnums[0](0). They are equal. Duplicate found. Do nothing.fastbecomes 2. - Step 2 (
fast = 2): Comparenums[2](1) withnums[1](0). They are different. New unique found.- Write
nums[2]tonums[slow](which isnums[1]). Array becomes[0, 1, 1, 1, 1, 2, 2]. - Increment
slowto 2. fastbecomes 3.
- Write
- Step 3 (
fast = 3): Comparenums[3](1) withnums[2](1). Equal. Ignore.fastbecomes 4. - Step 4 (
fast = 4): Comparenums[4](1) withnums[3](1). Equal. Ignore.fastbecomes 5. - Step 5 (
fast = 5): Comparenums[5](2) withnums[4](1). Different.- Write
nums[5]tonums[slow](which isnums[2]). Array becomes[0, 1, 2, 1, 1, 2, 2]. - Increment
slowto 3. fastbecomes 6.
- Write
- Step 6 (
fast = 6): Comparenums[6](2) withnums[5](2). Equal. Ignore.fastbecomes 7. - End:
fastis out of bounds. Returnslow(which is 3). The first 3 elements are[0, 1, 2].
Proof of Correctness
The algorithm maintains the invariant that nums[0...slow-1] contains the unique elements encountered so far in sorted order.
- Base Case: At index 0, the element is trivially unique.
slowstarts at 1, preserving this. - Inductive Step: When
fastmoves, we check ifnums[fast] != nums[fast-1]. Since the array is sorted, a change in value implies a strictly greater value, which has not been written to the unique prefix yet. By copyingnums[fast]tonums[slow], we extend the unique prefix. - Termination:
fastvisits every element. Therefore, all unique transitions are captured.slowends up at the count of unique elements.
Pattern Reuse Notes
The Two Pointers - In-place Array Modification pattern is a fundamental technique for array manipulation. Understanding the "read/write" pointer dynamic enables you to solve several related problems efficiently:
- LeetCode 27: Remove Element - Identical pattern, but the condition for writing is checking against a specific value rather than the previous element.
- LeetCode 75: Sort Colors - A more complex variation using three pointers to partition the array in-place.
- LeetCode 80: Remove Duplicates from Sorted Array II - An extension where at most two duplicates are allowed. The logic is nearly identical, checking
nums[fast]againstnums[slow-2]. - LeetCode 283: Move Zeroes - Uses the same read/write pointer logic to shift non-zero elements to the front.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 26
1class Solution {
2public:
3 int removeDuplicates(vector<int>& nums) {
4 // Edge case: constraints say length >= 1, so no need to check for empty.
5
6 int slow = 1; // The write pointer
7
8 // fast is the read pointer
9 for (int fast = 1; fast < nums.size(); fast++) {
10 // Compare current element with the previous one
11 if (nums[fast] != nums[fast - 1]) {
12 // Found a unique element, write it to the slow position
13 nums[slow] = nums[fast];
14 slow++;
15 }
16 }
17
18 return slow; // slow represents the number of unique elements
19 }
20};Java Solution for LeetCode 26
1class Solution {
2 public int removeDuplicates(int[] nums) {
3 // Constraints guarantee nums.length >= 1
4
5 int slow = 1; // Pointer for the position of the next unique element
6
7 for (int fast = 1; fast < nums.length; fast++) {
8 // If current element is different from the previous one, it is unique
9 if (nums[fast] != nums[fast - 1]) {
10 nums[slow] = nums[fast];
11 slow++;
12 }
13 }
14
15 return slow;
16 }
17}Python Solution for LeetCode 26
1class Solution:
2 def removeDuplicates(self, nums: List[int]) -> int:
3 # Constraints guarantee len(nums) >= 1
4
5 slow = 1 # Write pointer
6
7 # Fast pointer iterates through the list
8 for fast in range(1, len(nums)):
9 # Check if current element is different from the previous one
10 if nums[fast] != nums[fast - 1]:
11 nums[slow] = nums[fast]
12 slow += 1
13
14 return slow