题目描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。时间复杂度o(n),空间复杂度o(1)
public static void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
int temp = 0;
for (int i = 0; i < array.length; i++) {
//找出异或消除其他数后,这两个数的异或结果
temp = temp ^ array[i];
}
int temp1;
//可以消除一个二进制数中为1的最低位
temp1 = temp & (temp - 1);
int temp2;
//获得为1的最低位的数值
temp2 = temp - temp1;
num1[0]=0;
num2[0]=0;
for (int i = 0; i < array.length; i++) {
//为1的最低位是经过异或得到的,所以这两个数在
//这位上一定有个为1,一个为0,否则异或结果为0
if ((array[i] & temp2) == temp2) {
num1[0] = num1[0] ^ array[i];
} else {
num2[0] = num2[0] ^ array[i];
}
}
}
– 此题的原型:一个整型数组里除了一个数字之外,其他的数字都出现了两次。原型的解题思路是,对所有元素进行异或运算,即可得到结果。异或运算的具有异或自己为0,异或0为自己的特点。本质:0^1=1,1^0=1;1^1=0,0^0=0;
– 本题要求两个数,我们只需要对上面的过程进行加工即可得到结果对上面的异或结果我们找到某一位为1,可以找为1的最小位,通过flag=x-x&(x-1)就可以找到。找这个的目的是为了将这两个数划分开我们通过flag将数组分为两部分,对这两部分分别异或,即可得这两个数
– 例如,对于{2,4,3,6,3,2,5,5},首先异或2^4^3^6^3^2^5^5,得到temp=2,temp为出现一次的两个数4和6异或的结果,如果这个结果中的某位为1的话,对于这位,这两个数必然有个是1,有个是0,例如对于temp=2,说明4和6中必然有且仅有一个在第二位上为1,另一个在第二位上为0,因为temp=2是异或出来的,想想异或的规则。现在要做的事,我们如何找到temp=2上的1,这里我们为了提高效率,找为1的最低位,通过temp1=temp-temp&(temp-1)=2,即可得到temp中为1的最低位是what,得到这个temp1,我们就可以用temp1=2来划分开题目的要求的两个数字。通过temp1=2我们把整形数组划分为两个数组{2,3,6,3,2},{4,5,5},当然这两个数也被划分在这两个数组了,然后对这两个数组分别异或,即可得到最终结果