Given an integer array of size n+2 containing elements between 1 and n with two element repeating, find both duplicate elements without using any extra memory in linear time.

For example,

Input:  arr[] = [4, 3, 6, 5, 2, 4, 1, 1]
 
Output: The duplicate elements are 1 and 4

Practice this problem

 
Related Post:

Find two odd occurring elements in an array without using any extra space

 
For an input containing n elements, we can use hashing to solve this problem in O(n) time. The idea is to traverse the array and maintain the frequency of each element in a hash table. Then, after each array element is processed, return the elements with a frequency of two. The problem with this approach is that it requires O(n) extra space as well. Also, it requires one traversal of the array and one traversal of the hash table. The advantage of this approach is its simplicity and the fact that it will work for any number of duplicate elements present in the array.

 
We can solve this problem in a single traversal of the array and constant space. The idea is to use the XOR operator. We know that if we XOR a number with itself an odd number of times, the result is the number itself; otherwise, if we XOR a number an even number of times with itself, the result is 0. Also, XOR with 0 is always the number itself.

XOR of ‘x’ with 0:
 
x ^ 0 = x
 
 
XOR of ‘x’ with itself even number of times:
 
x ^ x = 0
x ^ x ^ x ^ x = (x ^ x) ^ (x ^ x) = 0 ^ 0 = 0
 
 
XOR of ‘x’ with itself odd number of times:
 
(x ^ x ^ x) = (x ^ (x ^ x)) = (x ^ 0) = x
(x ^ x ^ x ^ x ^ x) = (x ^ (x ^ x) ^ (x ^ x)) = (x ^ 0 ^ 0) = x

If we take XOR of all array elements with every element in range [1, n], even appearing elements will cancel each other. We are left with XOR of x and y, x ^ y, where x and y are two duplicate elements. Note that the duplicate elements will be XORed three times in total, whereas all other elements will be XORed twice.

How to find x and y?

We know that any set bit in result = (x ^ y) will be either set in x or y (but not in both as a bit will only set in result when it is set in one number and unset in the other).

The idea is to consider the rightmost set bit in result (or any other set bit) and split the array/range into two lists:

  1. The first list contains all the array elements and numbers in the range that have this bit set.
  2. The second list contains all the array elements and numbers in the range that have this bit unset.

As this rightmost bit is set in one number and unset in the other, we will have one duplicate element in each list. Basically, we have isolated traits of one number with the other, so that both x and y will go to different lists.

Now iterate each list once more, do XOR on each element in the list, and the result will be the duplicate element present in that list (since elements appearing twice will cancel each other).

 
Following is the implementation in C++, Java, and Python based on the above idea:

C++


Download  Run Code

Output:

The duplicate elements are 1 and 4

Java


Download  Run Code

Output:

The duplicate elements are 1 and 4

Python


Download  Run Code

Output:

The duplicate elements are 1 and 4