Remove Duplicates from Sorted Array - Complete Solution Guide
Remove Duplicates from Sorted Array is LeetCode problem 26, a Easy level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
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 things: Change the array nums such that the first k elements of nums contain the unique elements in the order they were present in nums initia
Detailed Explanation
This problem asks us to refine an already sorted array, `nums`, by removing duplicate elements directly within the array itself. The core constraint is 'in-place' modification: we're not allowed to create a new array. Instead, we must rearrange `nums` such that its initial `k` elements contain only the unique values, maintaining their original relative order. What happens to the elements beyond the `k`-th position doesn't matter for the problem's success criteria, though they will typically be duplicates that were overwritten. For example, if `nums = [0,0,1,1,1,2,2,3,3,4]`, the expected outcome is that `nums` is modified to `[0,1,2,3,4,_,_,_,_,_]` (where `_` signifies irrelevant values) and the function returns `k=5`. The challenge lies in efficiently identifying and relocating unique elements without using additional space, leveraging the fact that the array is already sorted in non-decreasing order. This sorted property is a huge hint, simplifying what would otherwise be a much more complex task. The trickiness comes from the simultaneous requirements of in-place modification, preserving relative order, and returning only the count `k`. We're effectively compacting the array, pushing all unique values to the front and reporting the new effective 'length' of the array that contains only unique values. The remaining space at the end of the array is essentially 'dead space' after the operation.
Solution Approach
The most intuitive and efficient approach for this problem, given the sorted input, is to use a two-pointer technique. We can think of these as a 'write' pointer and a 'read' pointer. Let `k` be our 'write' pointer (or more accurately, the index where the *next* unique element should be placed). It also conveniently represents the count of unique elements found so far. We initialize `k` to 1 because the first element `nums[0]` is always unique in any non-empty array. The 'read' pointer, implicitly `i` in the loop `for i in range(1, len(nums))`, iterates through the array starting from the second element. For each element `nums[i]`, we compare it with the element immediately preceding it, `nums[i-1]`. Since the array is sorted, if `nums[i]` is *different* from `nums[i-1]`, it means we've encountered a new unique number that hasn't been added to our unique prefix yet. In this scenario, we take this newly found unique element `nums[i]` and place it at the `nums[k]` position, then increment `k`. If `nums[i]` is the same as `nums[i-1]`, it's a duplicate, and we simply skip it, letting the 'read' pointer `i` advance while the 'write' pointer `k` stays put. This process continues until the 'read' pointer has traversed the entire array. By the end, `k` will hold the total count of unique elements, and the first `k` positions of `nums` will contain these unique elements in their original relative order. This approach works elegantly because the sorted nature guarantees that duplicates are always adjacent, and the two pointers effectively compress the unique elements to the array's front in a single pass.
Step-by-Step Algorithm
- Step 1: Handle the empty array case. If the input array is empty, return 0.
- Step 2: Initialize `k` to 1. This represents the index of the second unique element (the first unique element is already at index 0).
- Step 3: Iterate through the array starting from the second element (index 1).
- Step 4: For each element, compare it with the previous element. If they are different, it's a unique element.
- Step 5: If it's a unique element, place it at index `k` in the array (`nums[k] = nums[i]`) and increment `k`.
- Step 6: After the loop, `k` holds the number of unique elements, which is returned as the result.
Key Insights
- **Leveraging Sorted Property:** The entire efficiency of this solution hinges on the input array `nums` being sorted. This allows us to detect duplicates by simply comparing `nums[i]` with `nums[i-1]`. If they differ, `nums[i]` *must* be a new unique element because all prior elements up to `nums[i-1]` have already been processed for uniqueness.
- **Distinct Roles of Two Pointers:** The solution cleverly employs two pointers with different responsibilities: an explicit 'write' pointer (`k`) that points to the next available slot for a unique element and implicitly tracks the count of unique elements, and an implicit 'read' pointer (`i`) that scans through the entire array. The 'write' pointer only advances when a truly new unique element is discovered, effectively compacting the array in-place.
- **Problem's 'In-place' Definition:** Understanding that 'in-place' removal doesn't mean truly shrinking the array or invalidating memory. It specifically means constructing a unique-element prefix within the *original* `nums` array and returning the length of this prefix (`k`). Elements beyond index `k-1` are inconsequential to the problem's success criteria, making the modification straightforward without complex memory management.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(1)
Topics
This problem involves: Array, Two Pointers.
Companies
Asked at: Accenture, Adobe, Amazon, Apple, Bloomberg, Capgemini, Cisco, Cognizant, Flipkart, Infosys, Meta, Microsoft, Morgan Stanley, Nagarro, Oracle, Qualcomm, SAP, Siemens, Uber, Wipro, Yahoo, ZScaler, Zoho, tcs.