如题:
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
假设一个数组arr1={1,2,3,4,5,1,2,3,4,6};这个数组中1,2,3,4出现两次,5、6分别出现一次。在C语言中,逻辑或的运算方式是相同为0,相异为1,所以可以先将这这个数组中的元素异或一边,结果是5^6,5的二进制是序列是101,6的二进制序列是110,5^6==101^110=011;异或中出现的1正是出现一次的数异或的结果。按照每位二进制数的最后一位是否为1进行分组。是1的为:1,1,3,3,5 不是1的为2 ,2,4,4,6,在分完组之后,每组依次异或,第一组会得到5,第二组在依次异或,则得到的结果是6(当然,也可以直接与原数组异或后的结果再与分组后异或的结果异或,即5^6^5=6,这样就找出数组中的单身狗了。
具体看代码:
void Find_Single_Dog(int* arr, int sz)
{
int ret = 0; //记录数组异或的结果
int i = 0;
for (i = 0; i < sz; i++)
{
ret ^= arr[i]; //依次异或,最后的结果就是两个单身狗异或的结果
}
/*ret=1^1^2^2^3^3^4^4^5^6=5^6=011*/
//找ret为1的位,以此来分组。
int pos = 0;
for (i = 0; i < 31; i++)
{
if ((ret >> i) & 1 == 1)
{
pos = i;
break;
}
}
//开始分组,按照每个元素的第pos是否为1开始
int single1 = 0;//记录第一个单身狗
int single2 = 0;
for (i = 0; i < sz; i++)
{
if (((arr[i] >> pos) & 1) == 1)
{
single1 ^= arr[i];
}
}
single2 = ret ^ single1; //ret= 5^6 single1=5 ret^single1=5^6^5=6,自动找到下一个单身狗
printf("%d,%d", single1, single2);
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
Find_Single_Dog(arr, sz);
return 0;
}