Find duplicate in array with a memory efficient approach
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Finding duplicates in an array is a common algorithmic problem and has applications in data analysis, databases, and software development. While there are straightforward approaches to solve this, the challenge often lies in optimizing both time and space complexity. This article presents a memory-efficient strategy for identifying duplicates in an array, focusing on technical explanations and examples.
Problem Statement
Given an array of integers, identify all the duplicate numbers in memory-efficient manner. The goal is to identify duplicates without using additional data structures like hash tables or sets, which consume extra memory proportional to the input size.
Naive Approaches and Limitations
- Brute Force:
Compare each element with every other element, resulting in a time complexity of . This approach saves memory but is inefficient for large arrays. - Sorting: Sort the array first and then check adjacent elements for duplicates. This improves the time complexity to but does not make any advancements in terms of memory efficiency as sorting algorithms typically require additional space.
- Hash Tables or Sets: Use a hash table or set to track already visited elements, achieving an optimal time complexity of but at the cost of additional space.
Memory-Efficient Approach: Using Negative Marking
Concept
The goal is to reduce the memory overhead associated with duplicate detection. This can be done by leveraging the input array itself for marking visited numbers while ensuring that the original data remains retrievable.
Assumptions
- The input array contains integers where each integer is in the range 1 to .
Algorithm
The negative marking technique is effective when the range of numbers in the array is limited to the length of the array. The algorithm involves marking visited positions in the array by negating the value at that position.
Steps:
- Iterate over each element in the array.
- For each element, compute an index corresponding to the absolute value of that element.
- Negate the value at the calculated index to mark it as visited.
- If an index points to an already negative number, it indicates that the corresponding element is a duplicate.
- Restore the array to its original state if needed, by negating the previously negated elements.
Example
Consider an array: `[3, 4, 1, 4, 2, 3, 6, 5, 6]`
- Start with the first element `3`. Access index `3-1=2`. Negate the element at index 2 (i.e., from `1` to `-1`).
- Move to the second element `4`. Access index `4-1=3`. Negate the element at index 3 (i.e., from `4` to `-4`).
- For the next element `1`, access index `1-1=0`. Negate array[0] (i.e., from `3` to `-3`).
- Repeat the steps until you come across an index where the value is already negative. Such indices correspond to duplicate numbers.
Code Implementation
Here's a Python implementation of the algorithm:
- Array Constraints: This approach requires that all elements fall within the specific range associated with the array's length.
- Usage Scenarios: Ideal for scenarios where memory resources are constrained or when arrays are large.
- Restoration: The array changes during processing but can be restored if necessary.

