问题:一个数组中,只有两个数字是出现奇数次,其他数字均出现偶数次,请找出出现奇数次的两个数字
这儿需要用到一个位运算的技巧,即找到一个数的二进制最右边为1的数,比如temp,即用此数取反加1再和原数按位与,即可找到最右边位为1,其他位为0的数字
temp & (~temp +1)
- 思路:
1、假设数组元素为[a,b,others],这里others表示一系列数,都是出现偶数次的,a和b出现奇数次,即要找的目标
2、首先将数组中所有元素按位异或,得到的结果为 a^b,比如为 0010 0010
3、找到 a^b的最右边为1 的数:即:0000 0010,说明a和b在从右到坐第二位上一个为0,一个为1
4、将数组中所有从右到左第二位为0的数按位异或,结果即a或b中的一个数
5、将步骤2中的a&b的结果与步骤4中找到的一个数按位异或,即找到另一个数,至此完成 - 代码实现:
典型的位运算的应用,如下:
package problem.bitwise;
public class TwoNumAppearOddTimes {
/*
题目:在一个数组中,只有两个数字出现了奇数次,其他的数字均出现偶数次,请找出这两个数字
*/
public static int[] findNum(int[] arr)
{
int[] results=new int[2];
int rs=0;
for(int elem:arr)
{
rs^=elem;
}
int temp=rs & (~rs +1);
int onlyOne=0;
for(int elem:arr)
{
if ((elem & temp)==0)
{
onlyOne^=elem;
}
}
results[0]=onlyOne;
results[1]=rs^onlyOne;
return results;
}
public static void main(String[] args) {
int[] arr={1,1,2,2,3,3,4,4,5,5,6,7,7,8,9,9,0,0};
int[] results=findNum(arr);
System.out.println(results[0]+"\t"+results[1]);
}
}
执行结果为:
8 6