题目:
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。找出这两个数字
分析:
1.首先将数组所有元素依次异或,因为相同的元素异或得到0,所以最终的答案就等于那2个唯一的元素num1^num2的值。
2.因为a,b不同,所以异或得到的答案肯定是不等于0的,那么我们就找到a^b的二进制表示中第一个为1的位.假设为n位,那么num1和num2在这一位上必定是一个为1,一个为0.
3.利用数组元素的第n位是否是1,将数组元素分为两组。
4. 接着我们就可以用(1)中的num1^num2的值在每个分组中异或每一个元素,最终就可以得到那2个唯一的元素。
代码如下:
void find_num(int arr[], int sz, int *num1, int * num2)
{
assert(arr);
int ret = 0;
int i = 0;
int pos = 0;
int tmp = 0;
*num1 = 0;
*num2 = 0;
for (i = 0; i < sz; i++)
{
ret ^= arr[i];
} //找到num1^num2的结果
tmp = ret;
while (ret)
{
if ((ret & 1)==1) //找到一个为1的位
{
break;
}
ret = ret >> 1; // 也可以 ret/=2;
++pos;
}
for (i = 0; i < sz; i++)
{
if ((arr[i] >> pos)&1)//找出position位为1数的数
{
*num1 ^= arr[i];
}
}
*num2 = *num1^tmp;
}
测试程序:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
int main()
{
int arr[] = { 1, 2, 3, 5, 1, 2, 3, 4, };
int sz = sizeof(arr) / sizeof(arr[0]);
int num1 = 0 ,num2 = 0;
find_num(arr, sz, &num1, &num2); //返回型参数
printf("%d %d\n", num1, num2);
system("pause");
return 0;
}
这里,对于
二进制的思想,我们需要格外注意!!!