因为两个数`a`,`b`,出现次数为奇数。可以知道所求的`a`不等于`b`,且对所有的数异或的值等价为:`a^b`。由于`a`不等于`b`,那么`a^b`(记作:`c`)的值必然不等于`0`。也就是说`c`的二进制表示必然存在一个`1`,那么在该位置`a`、`b`两个数的二进制表示必然不同。那么,`c ^` 所有该二进制位置为`0`的数,得到`a`(或者`b`);`c ^` 所有该二进制位置为`1`的数,得到`b`(或者`a`);
~~~
/**
* 假定数组中有两个数出现次数为奇数次,其余为偶数次。找出这两个数
* @param arr 待查找数组
* @return 下标数组
*/
public int[] getTwoNumber(int[] arr){
if(arr == null || arr.length == 0) return null;
int res = arr[0];
for (int i = 1; i < arr.length; i++) {
res = res ^ arr[i];
}
// 提取出res二进制位中最右侧的1所代表的数
int number = res & (~res + 1);
int a = 0;
for (int j : arr) {
if ((number & j) == 0) {
a = a ^ j;
}
}
int b = res ^ a;
return new int[]{a, b};
}
~~~
需要注意的是,对于某个非零的正数,如果需要找到其最右侧的1所代表的那个数,可以使用:
~~~
// 提取出res二进制位中最右侧的1所代表的数
int number = res & (~res + 1);
~~~