Given an integer array nums
of length n
where all the integers of nums
are in the range [1, n]
and each integer appears at most twice, return an array of all the integers that appears twice.
You must write an algorithm that runs in O(n)
time and uses only constant auxiliary space, excluding the space needed to store the output
Example 1:
Input: nums = [4,3,2,7,8,2,3,1] Output: [2,3]
Example 2:
Input: nums = [1,1,2] Output: [1]
Example 3:
Input: nums = [1] Output: []
Describe the optimal algorithm to solve this problem and include code. Explain the time and space complexity. Finally, discuss any edge cases.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method for finding duplicates is like comparing each item with every other item. We essentially check every possible pair to see if they match. If we find a match, we know we've found a duplicate.
Here's how the algorithm would work step-by-step:
def find_all_duplicates_brute_force(input_numbers):
duplicate_numbers = []
# Iterate through each number in the input list
for current_index in range(len(input_numbers)):
for comparison_index in range(len(input_numbers)):
# Avoid comparing the number to itself
if current_index != comparison_index:
if input_numbers[current_index] == input_numbers[comparison_index]:
# Prevent adding the same duplicate multiple times
if input_numbers[current_index] not in duplicate_numbers:
duplicate_numbers.append(input_numbers[current_index])
return duplicate_numbers
The trick here is to use the array itself as a kind of tracker. We exploit the fact that the array contains numbers within a specific range to mark seen numbers in place.
Here's how the algorithm would work step-by-step:
def find_duplicates(numbers):
duplicates = []
for index in range(len(numbers)):
current_number = abs(numbers[index])
corresponding_index = current_number - 1
# If the value at corresponding_index is negative, it's a duplicate
if numbers[corresponding_index] < 0:
duplicates.append(current_number)
# Mark the number as seen by negating the value at corresponding_index.
else:
numbers[corresponding_index] *= -1
# Restore original array values
for index in range(len(numbers)):
numbers[index] = abs(numbers[index])
return duplicates
Case | How to Handle |
---|---|
Null or empty input array | Return an empty list to indicate no duplicates are found in an invalid input. |
Input array with size 1 | Return an empty list because a single element cannot be a duplicate. |
Input array where all elements are the same | The algorithm should correctly identify this single element as duplicated n-1 times if n is the size of array, returning it once. |
Input array where all numbers from 1 to n are present exactly once (no duplicates) | Return an empty list because there are no duplicates as requested. |
Input array contains the number n multiple times | The algorithm handles repeated occurrences of n correctly because it's still within the [1,n] range. |
Large input array (close to memory limits) | Choose an algorithm with O(n) space complexity or less to avoid memory overflow, such as using in-place modification. |
Array with only two elements that are the same. | The algorithm should correctly identify this as a single duplicate to return. |
Input array contains Integer.MAX_VALUE | Ensure the algorithm doesn't cause integer overflow when performing calculations or comparisons involving MAX_VALUE. |