Amazon Interview Question
Software Engineer / DevelopersCountry: India
I think it works fine !! A very simple logic in fact.
Now, consider the example:
{1,1,3,5} the binary representation is:
{001,001,101,110}
The XOR value will then be: 011
On dividing the numbers based on the right most bit value set in XOR, the 2 groups are:
{1,1,3} and {5}
{001,001,101} and {110}
the x and y would then be:
x={101} y={110} x=3 and y=5
Hence it works
So does this solution rely on the assumption that given the XOR of 2 numbers, there's only 1 pair of unique numbers which can lead to this XOR? If so, I can produce many pairs of numbers with the same value of XOR.
Furthermore, the code is weird because while it works for some cases, it won't work for others, depending on what duplicates we have, as well as the 2 non-repeating numbers of course. Has anyone tried verifying that the code actually work by setting different pairs of numbers as the non-repeating ones?
I am going to try explain this more clearly.
First how xor works: if you have two numbers say 10 (1010) and 8 (1000), xor operation ( done using operator ^ ) will return the bits which are set in one number but not in the other.
10 -- 1010
08 -- 1000
---------------
^ -- 0010
---------------
Here the third bit is set(from right) in 10 but not in 8;
Now the problem states that there are 2n + 2 numbers such that n numbers are repeated.
eg. for n = 3: { 2, 3, 2, 4, 5, 4, 5, 6 }
there are two of ( 2, 4 & 5 ) but only one of ( 3 & 6 )
Lets take the first set of number that repeats..
when we xor a number with itself the result is zero.
2 ^ 2 = 0 (in binary: 10 ^ 10 )
4 ^ 4 = 0
5 ^ 5 = 0
Now we have actually got rid of the numbers that repeats twice.
so when we xor all the elements of the array : a[i] ^ a[i+1] ^ ... a[n], we would have performed, for the above example ( 2 ^ 3 ^ 2 ^ 4 ^ 5 ^ 4 ^ 5 ^ 6 )
Since the repeating elements are nullified :) we are left with ( 3 ^ 6 ), the xor of the two elements we need to find. If the elements are equal, the 2n+2 constraint is not valid and hence these two numbers would have also been nullified.
Now all we have to do is extract the two numbers (x, y) from ( 3 ^ 6 )
3 ^ 6 is
011
110
-----
101
-----
what we can infer from the above is that the last bit is set in one number and not in the other. ( and so does the first bit)
set_bit_no = xor & ~(xor-1);
This line in the above example by Rajat Rastogi can be replaced with
int set_bit_no = 1;
while ( ! ( xor & set_bit_no ) )
set_bit_no <<=1;
what it does is right shift, a bit at a time and check whether it is set in the result of ( 3 ^ 6 )
Why do we need this?
Because, when doing a xor, a bit is set only when it is set in one and not in the other. So we are actually isolating a trait of one number so that we can extract it from the result.
Now is the tricky part.
for(i = 0; i < n; i++)
{
if(arr[i] & set_bit_no)
x = x ^ arr[i]; /*XOR of first set */
else
y = y ^ arr[i]; /*XOR of second set*/
}
Our example array: { 2, 3, 2, 4, 5, 4, 5, 6 }
x & y is initially zero;
Again we apply the same principle, but this time we check whether the rightmost bit in set in one each element of the array..if its set, it will be removed when a pair of the same item is encountered and thus we will be able to extract x;
Then we also xor the elems which does not have the right most bit set. So, we will be extracting all the pairs with this bit not set and y ( the pairs cancel each other and y remains )
I have one other solution for it -
We can use hash to solve it. Here we have to choose the hash function carefully..
find_duplicate()
{
let i = 0
compute x = hash(a[i])
if(a[i] == a[hash])
{ i++ }
else
{ swap(a[0],a[x]) }
if (i <= n)
{ call find_duplicate(i) }
else
{ return i}
}
This will find the element required for the first case.
If we now run the same algo for another n times it will find the 2nd element too.
I do not believe it to be faster than Xor algo. It's beautiful.
Finding the exor all all elements gives a^b (where and b are the required numbers). Finding the rightmost set bit means finding the position of the bit which differs in both (so the bit in this position for one number will be 0 and for other as 1) . This rightmost bit is named as set_bit_no. so '&' with all numbers will separate out all number into two where these two numbers are separated out
I got it.
for the same pair of number a, we have a^a = 0. Therefore, for N pairs, like a,b,c...a,b,c..., we still have a^b^c^...^a^b^c^...=0.
So if we have 2N+1 numbers with N pairs, the result of xor up all the number is the unrepeated one. If we have 2N+2 with N pairs and unrepeated number x y, the result = x^y and for sure result > 0. Then we split the numbers into two groups, to extract x and y respectively.
I am going to try explain this more clearly.
First how xor works: if you have two numbers say 10 (1010) and 8 (1000), xor operation ( done using operator ^ ) will return the bits which are set in one number but not in the other.
10 -- 1010
08 -- 1000
---------------
^ -- 0010
---------------
Here the third bit is set(from right) in 10 but not in 8;
Now the problem states that there are 2n + 2 numbers such that n numbers are repeated.
eg. for n = 3: { 2, 3, 2, 4, 5, 4, 5, 6 }
there are two of ( 2, 4 & 5 ) but only one of ( 3 & 6 )
Lets take the first set of number that repeats..
when we xor a number with itself the result is zero.
2 ^ 2 = 0 (in binary: 10 ^ 10 )
4 ^ 4 = 0
5 ^ 5 = 0
Now we have actually got rid of the numbers that repeats twice.
so when we xor all the elements of the array : a[i] ^ a[i+1] ^ ... a[n], we would have performed, for the above example ( 2 ^ 3 ^ 2 ^ 4 ^ 5 ^ 4 ^ 5 ^ 6 )
Since the repeating elements are nullified :) we are left with ( 3 ^ 6 ), the xor of the two elements we need to find. If the elements are equal, the 2n+2 constraint is not valid and hence these two numbers would have also been nullified.
Now all we have to do is extract the two numbers (x, y) from ( 3 ^ 6 )
3 ^ 6 is
011
110
-----
101
-----
what we can infer from the above is that the last bit is set in one number and not in the other. ( and so does the first bit)
set_bit_no = xor & ~(xor-1);
This line in the above example by Rajat Rastogi can be replaced with
int set_bit_no = 1;
while ( ! ( xor & set_bit_no ) )
set_bit_no <<=1;
what it does is right shift, a bit at a time and check whether it is set in the result of ( 3 ^ 6 )
Why do we need this?
Because, when doing a xor, a bit is set only when it is set in one and not in the other. So we are actually isolating a trait of one number so that we can extract it from the result.
Now is the tricky part.
for(i = 0; i < n; i++)
{
if(arr[i] & set_bit_no)
x = x ^ arr[i]; /*XOR of first set */
else
y = y ^ arr[i]; /*XOR of second set*/
}
Our example array: { 2, 3, 2, 4, 5, 4, 5, 6 }
x & y is initially zero;
Again we apply the same principle, but this time we check whether the rightmost bit in set in one each element of the array..if its set, it will be removed when a pair of the same item is encountered and thus we will be able to extract x;
Then we also xor the elems which does not have the right most bit set. So, we will be extracting all the pairs with this bit not set and y ( the pairs cancel each other and y remains )
I am going to try explain this more clearly.
First how xor works: if you have two numbers say 10 (1010) and 8 (1000), xor operation ( done using operator ^ ) will return the bits which are set in one number but not in the other.
10 -- 1010
08 -- 1000
---------------
^ -- 0010
---------------
Here the third bit is set(from right) in 10 but not in 8;
Now the problem states that there are 2n + 2 numbers such that n numbers are repeated.
eg. for n = 3: { 2, 3, 2, 4, 5, 4, 5, 6 }
there are two of ( 2, 4 & 5 ) but only one of ( 3 & 6 )
Lets take the first set of number that repeats..
when we xor a number with itself the result is zero.
2 ^ 2 = 0 (in binary: 10 ^ 10 )
4 ^ 4 = 0
5 ^ 5 = 0
Now we have actually got rid of the numbers that repeats twice.
so when we xor all the elements of the array : a[i] ^ a[i+1] ^ ... a[n], we would have performed, for the above example ( 2 ^ 3 ^ 2 ^ 4 ^ 5 ^ 4 ^ 5 ^ 6 )
Since the repeating elements are nullified :) we are left with ( 3 ^ 6 ), the xor of the two elements we need to find. If the elements are equal, the 2n+2 constraint is not valid and hence these two numbers would have also been nullified.
Now all we have to do is extract the two numbers (x, y) from ( 3 ^ 6 )
3 ^ 6 is
011
110
-----
101
-----
what we can infer from the above is that the last bit is set in one number and not in the other. ( and so does the first bit)
set_bit_no = xor & ~(xor-1);
This line in the above example by Rajat Rastogi can be replaced with
int set_bit_no = 1;
while ( ! ( xor & set_bit_no ) )
set_bit_no <<=1;
what it does is right shift, a bit at a time and check whether it is set in the result of ( 3 ^ 6 )
Why do we need this?
Because, when doing a xor, a bit is set only when it is set in one and not in the other. So we are actually isolating a trait of one number so that we can extract it from the result.
Now is the tricky part.
for(i = 0; i < n; i++)
{
if(arr[i] & set_bit_no)
x = x ^ arr[i]; /*XOR of first set */
else
y = y ^ arr[i]; /*XOR of second set*/
}
Our example array: { 2, 3, 2, 4, 5, 4, 5, 6 }
x & y is initially zero;
Again we apply the same principle, but this time we check whether the rightmost bit in set in one each element of the array..if its set, it will be removed when a pair of the same item is encountered and thus we will be able to extract x;
Then we also xor the elems which does not have the right most bit set. So, we will be extracting all the pairs with this bit not set and y ( the pairs cancel each other and y remains )
I am going to try explain this more clearly.
First how xor works: if you have two numbers say 10 (1010) and 8 (1000), xor operation ( done using operator ^ ) will return the bits which are set in one number but not in the other.
10 -- 1010
08 -- 1000
---------------
^ -- 0010
---------------
Here the third bit is set(from right) in 10 but not in 8;
Now the problem states that there are 2n + 2 numbers such that n numbers are repeated.
eg. for n = 3: { 2, 3, 2, 4, 5, 4, 5, 6 }
there are two of ( 2, 4 & 5 ) but only one of ( 3 & 6 )
Lets take the first set of number that repeats..
when we xor a number with itself the result is zero.
2 ^ 2 = 0 (in binary: 10 ^ 10 )
4 ^ 4 = 0
5 ^ 5 = 0
Now we have actually got rid of the numbers that repeats twice.
so when we xor all the elements of the array : a[i] ^ a[i+1] ^ ... a[n], we would have performed, for the above example ( 2 ^ 3 ^ 2 ^ 4 ^ 5 ^ 4 ^ 5 ^ 6 )
Since the repeating elements are nullified :) we are left with ( 3 ^ 6 ), the xor of the two elements we need to find. If the elements are equal, the 2n+2 constraint is not valid and hence these two numbers would have also been nullified.
Now all we have to do is extract the two numbers (x, y) from ( 3 ^ 6 )
3 ^ 6 is
011
110
-----
101
-----
what we can infer from the above is that the last bit is set in one number and not in the other. ( and so does the first bit)
set_bit_no = xor & ~(xor-1);
This line in the above example by Rajat Rastogi can be replaced with
int set_bit_no = 1;
while ( ! ( xor & set_bit_no ) )
set_bit_no <<=1;
what it does is right shift, a bit at a time and check whether it is set in the result of ( 3 ^ 6 )
Why do we need this?
Because, when doing a xor, a bit is set only when it is set in one and not in the other. So we are actually isolating a trait of one number so that we can extract it from the result.
Now is the tricky part.
for(i = 0; i < n; i++)
{
if(arr[i] & set_bit_no)
x = x ^ arr[i]; /*XOR of first set */
else
y = y ^ arr[i]; /*XOR of second set*/
}
Our example array: { 2, 3, 2, 4, 5, 4, 5, 6 }
x & y is initially zero;
Again we apply the same principle, but this time we check whether the rightmost bit in set in one each element of the array..if its set, it will be removed when a pair of the same item is encountered and thus we will be able to extract x;
Then we also xor the elems which does not have the right most bit set. So, we will be extracting all the pairs with this bit not set and y ( the pairs cancel each other and y remains )
I am going to try explain this more clearly.
First how xor works: if you have two numbers say 10 (1010) and 8 (1000), xor operation ( done using operator ^ ) will return the bits which are set in one number but not in the other.
10 -- 1010
08 -- 1000
---------------
^ -- 0010
---------------
Here the third bit is set(from right) in 10 but not in 8;
Now the problem states that there are 2n + 2 numbers such that n numbers are repeated.
eg. for n = 3: { 2, 3, 2, 4, 5, 4, 5, 6 }
there are two of ( 2, 4 & 5 ) but only one of ( 3 & 6 )
Lets take the first set of number that repeats..
when we xor a number with itself the result is zero.
2 ^ 2 = 0 (in binary: 10 ^ 10 )
4 ^ 4 = 0
5 ^ 5 = 0
Now we have actually got rid of the numbers that repeats twice.
so when we xor all the elements of the array : a[i] ^ a[i+1] ^ ... a[n], we would have performed, for the above example ( 2 ^ 3 ^ 2 ^ 4 ^ 5 ^ 4 ^ 5 ^ 6 )
Since the repeating elements are nullified :) we are left with ( 3 ^ 6 ), the xor of the two elements we need to find. If the elements are equal, the 2n+2 constraint is not valid and hence these two numbers would have also been nullified.
Now all we have to do is extract the two numbers (x, y) from ( 3 ^ 6 )
3 ^ 6 is
011
110
-----
101
-----
what we can infer from the above is that the last bit is set in one number and not in the other. ( and so does the first bit)
set_bit_no = xor & ~(xor-1);
This line in the above example by Rajat Rastogi can be replaced with
int set_bit_no = 1;
while ( ! ( xor & set_bit_no ) )
set_bit_no <<=1;
what it does is right shift, a bit at a time and check whether it is set in the result of ( 3 ^ 6 )
Why do we need this?
Because, when doing a xor, a bit is set only when it is set in one and not in the other. So we are actually isolating a trait of one number so that we can extract it from the result.
Now is the tricky part.
for(i = 0; i < n; i++)
{
if(arr[i] & set_bit_no)
x = x ^ arr[i]; /*XOR of first set */
else
y = y ^ arr[i]; /*XOR of second set*/
}
Our example array: { 2, 3, 2, 4, 5, 4, 5, 6 }
x & y is initially zero;
Again we apply the same principle, but this time we check whether the rightmost bit in set in one each element of the array..if its set, it will be removed when a pair of the same item is encountered and thus we will be able to extract x;
Then we also xor the elems which does not have the right most bit set. So, we will be extracting all the pairs with this bit not set and y ( the pairs cancel each other and y remains )
I have idea to solve this but this contain extra space and my algo is limit to 0-9 number and this code can check to n no of time number not repeated
b[10]={0,0,0,0,0,0,0,0,0,0}//Storing initial value to it for(i=0;i<array.length;i++)
{
if(b[array[i]])
{
b[array[i]]=b[array[i]]-array[i];//subtracting number if it is repeated
}
else
b[array[i]]=array[i];//storing value in array
}
for(i=0;i<10;i++)
{
if(b[i])
printf("%d",b[i]);
}
If we can use extra memory, then using hashmaps we can do it. For each element we add hash(array[i])=1; and whenever we find containsKey(array[i])..we delete it so that at the end of scanning all the elements in array in hashmap we will be left with only one element.
If he asks for 2 or more, then all the remaining elements in the map are unique.
@shreyas we can't use extra space.although he gave me hint using xor into two groups but i could not understand his logic :(
We can solve 2n+2 array problem using the xor property. In first pass xor all the elements. now we have xor of two no.'s as output. now find the rightmost set bit of this output by using
mask = output & (output-1)
and this bit will be set in one of the no. so now use second pass and make two partitions of no. using this
mask
{if no. & mask == true
then a=a xor no.
else
b=b xor no.
}
by using this you can find both the no.
Taken from geeksforgeeks
- Rajat Rastogi February 03, 2012