因為兩個數`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);
~~~