题目要求:
在一个数组中,其余数字都是成堆出现的,只有两个数字出现了一次。尽快找到这两个数字。
思路:
之前有过类似题,是一组数组中只有一个数字出现了一次,其余数字都是成对出现的。找到这个数字。这道题直接异或就可以得出结果。但是若数组中有两个只出现了一次的数字,再用异或得出的就是两个只出现一次的数字异或的结果。即数组若为{1 2 3 3 2 1 4 5}结果就为4 5的异或结果,但若将4 5分的不同的组,再进行异或就能找到4 5。既然两个数字不相同,那么它们在某一位bit上肯定是不同的,那我们就可以根据这来进行分组。
int arr[]={1,2,3,3,2,1,4,5}
异或结果:4^5即0100^0101=0001即bit最低位就不同,所以整个数组就可以根据最低位是1还是0来分
arr[0]=0001 第二组 arr[4]=0010 第一组
arr[1]=0010 第一组 arr[5]=0001 第二组
arr[2]=0011 第二组 arr[6]=0100 第一组
arr[3]=0011 第二组 arr[7]=0101 第二组
这样就将数组分为两组了,就转换成一组数组中只有一个数字出现了一次的问题。
直接进行异或就能分别找出只出现了一次的两个数字。
#include<stdio.h>
#include<assert.h>
void FindTwoDifferent(int *arr,int len)
{
int fin=0;
int i=0,j=0;
int different1=0,different2=0;
assert(arr);
for(i=0;i<len;i++)
{
fin^=arr[i];
}
while(i<32)
{
if(fin&1==1)//这两个数字在32个bit上第i个位不同
break;
fin>>=1;
i++;
j=i;
}
for(i=0;i<len;i++)//进行分组
{
if(((arr[i]>>j)&1)==0)
different1^=arr[i];
else
different2^=arr[i];
}
printf("Different Two:%d %d\n",different1,different2);
}
int main()
{
int arr[]={1,2,3,4,5,4,3,2,1,6};
int sz=sizeof(arr)/sizeof(arr[0]);
FindTwoDifferent(arr,sz);
return 0;
}