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 use only constant memory space.
Note: The repeating element should be printed only once.
Example:
Input: n=7 , 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
Apprach 1:
Modify the array elements by making visited elements negative (if visited once) or greater than n (if visited twice or more).
Follow the steps to implement the approach:
- Iterate Through the Array
- Calculate an index based on the absolute value of each element.
- If the index is equal to ‘n,‘ count it as the largest element.
- If the element at the calculated index is negative, add (index – 1) to the result vector and modify the element at that index.
- If there are more than one largest elements, add ‘n – 1’ to the result vector.
- If the result vector is empty, add ‘-1‘ to it.
- Otherwise, sort the result vector.
- Return the Result Vector
Below is the implementation of above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > duplicates( int arr[], int n)
{
for ( int i = 0; i < n; i++) {
arr[i] += 1;
}
vector< int > res;
int count = 0;
for ( int i = 0; i < n; i++) {
int index = abs (arr[i]) > n ? abs (arr[i]) / (n + 1)
: abs (arr[i]);
if (index == n) {
count++;
continue ;
}
int val = arr[index];
if (val < 0) {
res.push_back(index - 1);
arr[index] = abs (arr[index]) * (n + 1);
}
else if (val > n)
continue ;
else
arr[index] = -arr[index];
}
if (count > 1)
res.push_back(n - 1);
if (res.size() == 0)
res.push_back(-1);
else
sort(res.begin(), res.end());
return res;
}
int main()
{
int numRay[] = { 0, 4, 3, 2, 7, 8, 2, 3, 1 };
int n = sizeof (numRay) / sizeof (numRay[0]);
vector< int > ans = duplicates(numRay, n);
for ( int i : ans)
cout << i << ' ' << endl;
return 0;
}
|
Java
import java.util.*;
public class Solution {
static ArrayList<Integer> duplicates( int arr[], int n)
{
for ( int i = 0 ; i < n; i++) {
arr[i] += 1 ;
}
ArrayList<Integer> res = new ArrayList<>();
int count = 0 ;
for ( int i = 0 ; i < n; i++) {
int index = Math.abs(arr[i]) > n
? Math.abs(arr[i]) / (n + 1 )
: Math.abs(arr[i]);
if (index == n) {
count++;
continue ;
}
int val = arr[index];
if (val < 0 ) {
res.add(index - 1 );
arr[index] = Math.abs(arr[index]) * (n + 1 );
}
else if (val > n)
continue ;
else
arr[index] = -arr[index];
}
if (count > 1 )
res.add(n - 1 );
if (res.size() == 0 )
res.add(- 1 );
else
Collections.sort(res);
return res;
}
public static void main(String[] args)
{
int numRay[] = { 0 , 4 , 3 , 2 , 7 , 8 , 2 , 3 , 1 };
int n = numRay.length;
ArrayList<Integer> ans = duplicates(numRay, n);
for (Integer i : ans) {
System.out.println(i);
}
}
}
|
Python3
def duplicates(arr, n):
for i in range (n):
arr[i] = arr[i] + 1
res = []
count = 0
for i in range (n):
if ( abs (arr[i]) > n):
index = abs (arr[i]) / / (n + 1 )
else :
index = abs (arr[i])
if (index = = n):
count + = 1
continue
val = arr[index]
if (val < 0 ):
res.append(index - 1 )
arr[index] = abs (arr[index]) * (n + 1 )
elif (val>n):
continue
else :
arr[index] = - arr[index]
if (count > 1 ):
res.append(n - 1 )
if ( len (res) = = 0 ):
res.append( - 1 )
else :
res.sort()
return res
numRay = [ 0 , 4 , 3 , 2 , 7 , 8 , 2 , 3 , 1 ]
n = len (numRay)
ans = duplicates(numRay,n)
for i in ans:
print (i)
|
C#
using System;
using System.Collections.Generic;
public class HelloWorld {
public static List< int > duplicates( int [] arr, int n)
{
for ( int i = 0; i < n; i++) {
arr[i] += 1;
}
List< int > res = new List< int >();
int count = 0;
for ( int i = 0; i < n; i++) {
int index = Math.Abs(arr[i]) > n
? Math.Abs(arr[i]) / (n + 1)
: Math.Abs(arr[i]);
if (index == n) {
count++;
continue ;
}
int val = arr[index];
if (val < 0) {
res.Add(index - 1);
arr[index] = Math.Abs(arr[index]) * (n + 1);
}
else if (val > n)
continue ;
else
arr[index] = -1 * arr[index];
}
if (count > 1)
res.Add(n - 1);
if (res.Count == 0)
res.Add(-1);
else
res.Sort();
return res;
}
public static void Main( string [] args)
{
int [] numRay = { 0, 4, 3, 2, 7, 8, 2, 3, 1 };
int n = numRay.Length;
List< int > ans = duplicates(numRay, n);
for ( int i = 0; i < ans.Count; i++) {
Console.WriteLine(ans[i]);
}
}
}
|
Javascript
function duplicates(arr, n) {
for (let i = 0; i < n; i++) {
arr[i] += 1;
}
let res = new Array();
let count = 0;
for (let i = 0; i < n; i++) {
let index = Math.abs(arr[i]) > n ? Math.abs(arr[i]) / (n + 1)
: Math.abs(arr[i]);
if (index == n) {
count++;
continue ;
}
let val = arr[index];
if (val < 0) {
res.push(index - 1);
arr[index] = Math.abs(arr[index]) * (n + 1);
}
else if (val > n)
continue ;
else
arr[index] = -arr[index];
}
if (count > 1)
res.push(n - 1);
if (res.length == 0)
res.push(-1);
else
res.sort( function (a, b) { return a - b });
return res;
}
let numRay = [0, 4, 3, 2, 7, 8, 2, 3, 1];
let n = numRay.length;
let ans = duplicates(numRay, n);
for (let i = 0; i < ans.length; i++)
console.log(ans[i]);
|
Time Complexity: O(n), Only two traversals are needed. If the answer to be return should in ascending order, then in that case we will have to sort the list and complexity will become O(n logn).
Auxiliary Space: O(1). The extra space is used only for the array to be returned.
Apprach 2:
Use the input array to store the frequency of each element. While Traversing the array, if an element x is encountered then increase the value of x%n‘th index by n. The original value at ith index can be retrieved by arr[i]%n and frequency can be retrieved by dividing the element by n.
Follow the steps to implement the approach:
- Traverse the given array from start to end.
- For every element in the array increment the element arr[i] by n.
- Now traverse the array again and store all those indexes i for which arr[i]/n is greater than 1. Which guarantees that the number has appeared more than once.
- Since, the values are getting modified, the original value at ith index can be retrieved by arr[i]%n.
Below is the implementation of above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > duplicates( int arr[], int n)
{
vector< int > ans;
for ( int i = 0; i < n; i++) {
int index = arr[i] % n;
arr[index] += n;
}
for ( int i = 0; i < n; i++) {
if ((arr[i] / n) >= 2)
ans.push_back(i);
}
return ans;
}
int main()
{
int arr[] = { 1, 6, 3, 1, 3, 6, 6 };
int arr_size = sizeof (arr) / sizeof (arr[0]);
cout << "The repeating elements are: \n" ;
vector< int > ans = duplicates(arr, arr_size);
for ( auto x : ans)
cout << x << " " ;
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
public class Duplicates {
public static List<Integer> findDuplicates( int [] arr)
{
List<Integer> duplicates = new ArrayList<>();
int n = arr.length;
for ( int i = 0 ; i < n; i++) {
int index = arr[i] % n;
arr[index] += n;
}
for ( int i = 0 ; i < n; i++) {
if (arr[i] / n >= 2 ) {
duplicates.add(i);
}
}
return duplicates;
}
public static void main(String[] args)
{
int [] arr = { 1 , 6 , 3 , 1 , 3 , 6 , 6 };
System.out.println( "The repeating elements are: " );
List<Integer> ans = findDuplicates(arr);
for ( int x : ans) {
System.out.print(x + " " );
}
}
}
|
Python3
def find_duplicates(arr):
duplicates = []
n = len (arr)
for i in range (n):
index = arr[i] % n
arr[index] + = n
for i in range (n):
if arr[i] / / n > = 2 :
duplicates.append(i)
return duplicates
arr = [ 1 , 6 , 3 , 1 , 3 , 6 , 6 ]
print ( "The repeating elements are:" )
ans = find_duplicates(arr)
for x in ans:
print (x, end = " " )
|
C#
using System;
using System.Collections.Generic;
class Program {
static List< int > FindDuplicates( int [] arr)
{
List< int > duplicates = new List< int >();
int n = arr.Length;
for ( int i = 0; i < n; i++) {
int index = arr[i] % n;
arr[index] += n;
}
for ( int i = 0; i < n; i++) {
if (arr[i] / n >= 2) {
duplicates.Add(i);
}
}
return duplicates;
}
static void Main()
{
int [] arr = { 1, 6, 3, 1, 3, 6, 6 };
Console.WriteLine( "The repeating elements are:" );
List< int > ans = FindDuplicates(arr);
foreach ( int x in ans) { Console.Write(x + " " ); }
}
}
|
Javascript
function findDuplicates(arr) {
const duplicates = [];
const n = arr.length;
for (let i = 0; i < n; i++) {
const index = arr[i] % n;
arr[index] += n;
}
for (let i = 0; i < n; i++) {
if (arr[i] / n >= 2) {
duplicates.push(i);
}
}
return duplicates;
}
const arr = [1, 6, 3, 1, 3, 6, 6];
console.log( "The repeating elements are:" );
const ans = findDuplicates(arr);
ans.forEach((x) => {
console.log(x + " " );
});
|
OutputThe repeating elements are:
1 3 6
Time Complexity: O(n), Only two traversals are needed. So the time complexity is O(n).
Auxiliary Space: O(1), The extra space is used only for the array to be returned.