Given an integer array, duplicates appear in it an even number of times except for two elements, which appear an odd number of times. Find both odd appearing elements without using any extra memory.

For example,

Input:  arr[] = [4, 3, 6, 2, 4, 2, 3, 4, 3, 3]
 
Output: The odd occurring elements are 4 and 6
 
6 appears once.
2 appears twice.
4 appears thrice.
3 appears 4 times.

Practice this problem

 
Related Post:

Find the odd occurring element in an array in a single traversal

 
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 odd frequencies. 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. This approach’s advantage is its simplicity and the fact that it will work for any number of distinct odd elements present in the array.

 
We can solve this problem in O(1) space by using 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

So, if we take XOR of all array elements, even appearing elements will cancel each other, and we are left with XOR of x and y, x ^ y, where x and y are two odd appearing elements.

How to find x and y?

Let result = (x ^ y).

We know that any set bit in result 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 into two subarrays:

  1. All elements that have this bit set.
  2. All elements that have this bit unset.

As this rightmost bit is set in one number and unset in the other, we will have one odd appearing element in each subarray. We have isolated traits of one number with the other, so that both x and y will go to a different subarray.

Now iterate each subarray once more, do XOR on each element of the subarray, and the result will be the odd appearing element present in the subarray (since even appearing elements will cancel each other).

 
Following is the C++, Java, and Python implementation of the idea:

C++


Download  Run Code

Output:

The odd occurring elements are 6 and 4

Java


Download  Run Code

Output:

The odd occurring elements are 6 and 4

Python


Download  Run Code

Output:

The odd occurring elements are (6, 4)