I was solving a problem to find the repeating and missing numbers in an array with 1 to n numbers using the bit manipulation's XOR approach.
The following was the solution I found online-
public int[] repeatedNumber(final int[] arr) {
int xor1;
int n=arr.length;
int set_bit_no;
int i;
int x = 0;
int y = 0;
xor1 = arr[0];
/* Get the xor of all array elements */
for (i = 1; i < n; i++)
xor1 = xor1 ^ arr[i];
/* XOR the previous result with numbers from 1 to n*/
for (i = 1; i <= n; i++)
xor1 = xor1 ^ i;
/* Get the rightmost set bit in set_bit_no */
set_bit_no = xor1 & ~(xor1 - 1);
for (i = 0; i < n; i++) {
if ((arr[i] & set_bit_no) != 0)
/* arr[i] belongs to first set */
x = x ^ arr[i];
else
/* arr[i] belongs to second set*/
y = y ^ arr[i];
}
for (i = 1; i <= n; i++) {
if ((i & set_bit_no) != 0)
/* i belongs to first set */
x = x ^ i;
else
/* i belongs to second set*/
y = y ^ i;
}
for(int num : arr){
if(num==x)
return new int[]{x, y};
}
return new int[]{y,x};
}
After cracking my head for hours, I finally understood everything EXCEPT one line-
set_bit_no = xor1 & ~(xor1 - 1);
Now this is supposed to calculate the rightmost set bit for the final value after XOR operations. Even after testing this in debug mode and looking up YouTube videos, I have a few questions-
Let's say we have, in binary:
xor1: 0b00110111001000
xor1-1: 0b00110111000111
~(xor1-1): 0b11001000111000
xor1 & ~(xor1-1): 0b00000000001000
The secret is that subtracting one changes the trailing 0 bits to 1, and then changes the 1 bit to the left of those to 0 via borrow.
The bit manipulations after that isolate the single bit that changes from 1 to 0.
The name of the set_bit_no
variable is confusing, since it's not a bit number. It's a bit value.