Find duplicates in O(n) time and O(1) extra space | Set 1
Given an array of n elements that contains elements from 0 to n-1, with any of these numbers appearing any number of times. Find these repeating numbers in O(n) and using only constant memory space.
Example:
Input : n = 7 and array[] = {1, 2, 3, 6, 3, 6, 1} Output: 1, 3, 6 Explanation: The numbers 1 , 3 and 6 appears more than once in the array. Input : n = 5 and array[] = {1, 2, 3, 4 ,3} Output: 3 Explanation: The number 3 appears more than once in the array.
This problem is an extended version of the following problem.
Find the two repeating elements in a given array
Method 1 and Method 2 of the above link are not applicable as the question says O(n) time complexity and O(1) constant space. Also, Method 3 and Method 4 cannot be applied here because there can be more than 2 repeating elements in this problem. Method 5 can be extended to work for this problem. Below is the solution that is similar to Method 5.
Solution 1:
- Approach:The elements in the array is from 0 to n-1 and all of them are positive. So to find out the duplicate elements, a HashMap is required, but the question is to solve the problem in constant space. There is a catch, the array is of length n and the elements are from 0 to n-1 (n elements). The array can be used as a HashMap.
Problem in the below approach. This approach only works for arrays having at most 2 duplicate elements i.e It will not work if the array contains more than 2 duplicates of an element. For example: {1, 6, 3, 1, 3, 6, 6} it will give output as : 1 3 6 6. - Note: The above program doesn’t handle 0 cases (If 0 is present in array). The program can be easily modified to handle that also. It is not handled to keep the code simple. (Program can be modified to handle 0 cases by adding plus One(+1) to all the values. also subtracting One from the answer and by writing { arr [abs(arr[i]) – 1] } in code)
In other approach below, the discussed solution prints repeating elements only once.
- Approach: The basic idea is to use a HashMap to solve the problem. But there is a catch, the numbers in the array are from 0 to n-1, and the input array has length n. So, the input array can be used as a HashMap. While Traversing the array, if an element ‘a’ is encountered then increase the value of a%n‘th element by n. The frequency can be retrieved by dividing the a % n’th element by n.
- Algorithm:
- Traverse the given array from start to end.
- For every element in the array increment the arr[i]%n‘th element by n.
- Now traverse the array again and print all those indexes i for which arr[i]/n is greater than 1. Which guarantees that the number n has been added to that index
- This approach works because all elements are in the range from 0 to n-1 and arr[i] would be greater than n only if a value “i” has appeared more than once.
Implementation:
C++
// C++ code to find // duplicates in O(n) time #include <bits/stdc++.h> using namespace std; int main() { int numRay[] = { 0, 4, 3, 2, 7, 8, 2, 3, 1 }; int arr_size = sizeof (numRay) / sizeof (numRay[0]); // count the frequency for ( int i = 0; i < arr_size; i++) { numRay[numRay[i] % arr_size] = numRay[numRay[i] % arr_size] + arr_size; } cout << "The repeating elements are : " << endl; for ( int i = 0; i < arr_size; i++) { if (numRay[i] >= arr_size * 2) { cout << i << " " << endl; } } return 0; } // This code is contributed by aditya kumar (adityakumar129) |
C
// C++ code to find // duplicates in O(n) time #include <stdio.h> int main() { int numRay[] = { 0, 4, 3, 2, 7, 8, 2, 3, 1 }; int arr_size = sizeof (numRay) / sizeof (numRay[0]); // count the frequency for ( int i = 0; i < arr_size; i++) { numRay[numRay[i] % arr_size] = numRay[numRay[i] % arr_size] + arr_size; } printf ( "The repeating elements are : \n" ); for ( int i = 0; i < arr_size; i++) { if (numRay[i] >= arr_size * 2) { printf ( "%d \n" , i ); } } return 0; } // This code is contributed by aditya kumar (adityakumar129) |
Java
// JAVA code to find // duplicates in O(n) time class Leet442 { public static void main(String args[]) { int numRay[] = { 0 , 4 , 3 , 2 , 7 , 8 , 2 , 3 , 1 }; for ( int i = 0 ; i < numRay.length; i++) { numRay[numRay[i] % numRay.length] = numRay[numRay[i] % numRay.length] + numRay.length; } System.out.println( "The repeating elements are : " ); for ( int i = 0 ; i < numRay.length; i++) { if (numRay[i] >= numRay.length * 2 ) { System.out.println(i + " " ); } } } } |
Python
# Python3 code to find duplicates in O(n) time numRay = [ 0 , 4 , 3 , 2 , 7 , 8 , 2 , 3 , 1 ] arr_size = len (numRay) for i in range (arr_size): x = numRay[i] % arr_size numRay[x] = numRay[x] + arr_size print ( "The repeating elements are : " ) for i in range (arr_size): if (numRay[i] > = arr_size * 2 ): print (i, " " ) # This code is contributed by 29AjayKumar |
C#
// C# code to find // duplicates in O(n) time using System; class Leet442 { public static void Main(String []args) { int []numRay = { 0, 4, 3, 2, 7, 8, 2, 3, 1 }; for ( int i = 0; i < numRay.Length; i++) { numRay[numRay[i] % numRay.Length] = numRay[numRay[i] % numRay.Length] + numRay.Length; } Console.WriteLine( "The repeating elements are : " ); for ( int i = 0; i < numRay.Length; i++) { if (numRay[i] >= numRay.Length * 2) { Console.WriteLine(i + " " ); } } } } // This code is contributed by shivanisinghss2110 |
Javascript
<script> // Javascript code to find // duplicates in O(n) time let numRay = [ 0, 4, 3, 2, 7, 8, 2, 3, 1 ]; let arr_size = numRay.length; // count the frequency for (let i = 0; i < arr_size; i++) { numRay[numRay[i] % arr_size] = numRay[numRay[i] % arr_size] + arr_size; } document.write( "The repeating elements are : " + "</br>" ); for (let i = 0; i < arr_size; i++) { if (numRay[i] >= arr_size * 2) { document.write(i + " " + "</br>" ); } } // This code is contributed by mukesh07. </script> |
Output:
The repeating elements are : 2 3
Complexity Analysis:
- Time Complexity: O(n).
Only two traversals are needed. So the time complexity is O(n). - Auxiliary Space: O(1).
No extra space is needed, so the space complexity is constant.