#define _CRT_SECURE_NO_WARNINGS
#include<string.h>
#include <stdio.h>
#include<assert.h>
int main()
{
//一组数和0不断异或,最后得出的数就是唯一单着的;
//因为异或符合结合律和交换律;
//异或(^):二进制位相同为0,不同为1;所以两个完全相同的数异或结果一定为0;
//只有一个单身狗的情况;
/*int dog1 = 0;
int arr1[] = {1,5,6,5,2,7,7,6,1};
int sz1 = sizeof(arr1) / sizeof(arr1[0]);
for (int i=0;i<sz1;i++)
{
dog1 = dog1 ^ arr1[i];
}
printf("%d\n",dog1);*/
//两个单身狗的情况
//此处使用按位操作符较为合适,效率和可读性都比较高;
int ret = 0;
int arr[] = {1,5,6,5,2,7,6,7,1,3};//可以看到,单身狗数为2,3;
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
ret = ret ^ arr[i];//两个单身狗数按位异或的结果;
}
int count = 0;//标记变量;
for (int i=0;i<32;i++)
{
//按位异或:相同为0,不同为1;
//按位与:都为1结果才为1,否则为0;
//按位或:都为0结果才为0,否则为1;
//遍历ret(两个单身狗数按位异或的结果),第一次出现的1,则意味着两个数在此位不同;
//1的二进制补码: 00000000 00000000 00000000 00000001
if ( ( (ret>>i)&1 )==1 )//按位右移(针对二进制位),去除最后一位,左边补0;
{
//此处按位异或后的结果应该是 2^3==001;
//任何数和1按位与,前31位都为0,最后一位如果是1,那么结果等于1,否则结果为0;
//任何数和0按位与,结果都为 00000000 00000000 00000000 00000000;
//任何数和0按位或,结果都为它本身;
//任何数和0按位异或,结果也都为它本身;
count = i;//count意思是第几个二进制位不相同,此处count为0,跳出循环;
break;
}
}
//分组按位异或,把第count位相同的数分为一组;
int dog1 = 0;
int dog2 = 0;
//让两组数都从0开始异或,防止出现一个单身狗刚好单独在一组的情况;
for (int i=0;i<sz;i++)
{
if ( ( (arr[i]>>count) &1) ==1 )
//右移count(0)位后,最后一位为1的所有数开始按位异或;
{
//所以dog1应该为3;
dog1 = dog1 ^ arr[i];
}
else
{
dog2=dog2^arr[i];
}
}
//dog2 = ret ^ dog1;//此处相当于2^3^3,结果自然等于2;
printf("%d %d",dog1,dog2);
return 0;
}
(C语言)找单身狗
最新推荐文章于 2023-10-17 22:03:18 发布