我们知道,两个相同的数字异或后为0,两个不同的数字异或一定是不为0的.
0^0=0;
0^1=1;
1^1=0;
因此我们可以让这个数组里面的所有元素异或,异或后的结果就是这两个只出现一次的数字.
例如nums里的元素为 1,1,2,2,3,4,4,5,6,6.
1^1^2^2^3^4^4^5^6^6=3^5=6
0000 0011
^ 0000 0101
= 0000 0110 (异或后的结果)
现在就以上面的示例分析.
题目的要求是找到这两个数字,现在我们得出来的是这两个数异或后的结果,我们知道0和1的出现是看这两个数对应的位是否相同,可以看到异或后结果的第二(N)位为1,说明这两个数的对应的位是不同的.因此我们可以想是否可以利用这一个位来分离这个数组中只出现一次的两个数字,这显然是可行的.
用这一个位对nums数组进行异或,结果为1的放在一个数组中,结果为0的放在另一个数组中.
参照上面例子给出的元素
第二位为1的元素有2,2,3,6,6
第二位为0的元素有1,1,5,4,4
因此这个问题现在就被简化成在一个数组里,只有一个只出现一次的数字.因此很简单,就只需要用0分别异或这两个数组就行了.
0^2^2^3^6^6=3;
0^1^1^5^4^4=5;
int* singleNumber(int* nums, int numsSize, int* returnSize){
int ret=0;
int i=0;
//ret为异或后的结果
for(i=0;i<numsSize;i++)
{
ret^=nums[i];
}
//m是第N位为1的数,用来分离两个特别的数
int m=0;
while(m < 32)
{
if(ret & (1<<m))
break;
else
++m;
}
int x1=0;
int x2=0;
for(i=0;i<numsSize;i++)
{
//分离两个数
if(nums[i] & (1<<m))
x1^=nums[i];
else
x2^=nums[i];
}
int *Array=(int*)malloc(sizeof(int)*2);
Array[0]=x1;
Array[1]=x2;
*returnSize=2;
return Array;
}