在一个数组中寻找一只出现一次的的数字(单身狗)
当今社会 三人行 必有狗 是谁我不说
数组中也会出现 单身狗数字
例如数组 1 2 2 3 3 1 4中 4就是单身狗
思路 因为单身狗只有一个 直接全部异或
异或的特点相同为0,相异为1,
如果有重复的数字 异或就等于0 最后只会留一下一个单身狗
看代码
int main()
{
int arr[] = { 1,2,2,3,3,1,4 };
int dog = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
dog ^= arr[i];
}
printf("单身狗 是%d", dog);
return 0;
}
但是如果人多起来就不会只有一个单身狗 现在假如有两个单身狗我们该怎么找
如果我们按照之前的思路直接异或 肯定只会出来一个四不像数
假设数组1 2 3 3 1 4
思路 我们把 两个单身狗分成两个组
而组中其他的数字就都不是单身狗
此时我们在分组异或就分别得到了2个单身狗
问题 我们以什么为依据分组?
依据 二进制位
异或把相同的数字变成0,不同的数字变成1, 我们根据1在那位 就说明单身狗这个的二进制位不同 ,按照这个二进制位分
两个单身狗是不可能进到一组的
第一步 我们依然把数组中所有数字异或到一起 然后判断这个数字的二进制位 因为有两个单身狗
最后异或完毕得到了 6 6的二进制位是 0110 说明两个单身狗数字的二进制最后位是相等
我们左移一位得到了1 就说明 两个单身狗数字的倒数第二位二进制数 不相等
第二步 让数组中所有的数字左移一位 如果等于 1 放进第一个数组中
如果等于0 放进第二个数组中
第三步 把数组中的数字全部异或就得到了 2个单身狗
直接上代码
int main()
{
int arr[] = { 1,2,3,3,1,4 };
int sum = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
sum ^= arr[i];
}
int count = 0;
for (int i = 0; i < 32; i++)
{
if (sum & 1 <<i) //循环判断第几位是1
{
count = i;//如果是1 记录下来
break;
}
}
int dog1 = 0, dog2 = 0;
for (int i = 0; i < sz; i++)
{
if ( arr[i] & 1 <<count)
dog1 ^= arr[i];
else
dog2 ^= arr[i];
}
printf("第一个单身狗%d\n 第二个单身狗%d", dog1, dog2);
return 0;
}