单身狗数是指数组中只出现一次的数字,其他数字都在谈甜甜的恋爱,只有它还在当舔狗呜呜呜呜,也可能是拒绝恋爱脑,自律型男类,孤独是双刃的锋芒。
一阶的单身狗只需要通过异或的特性就可以找到他了,异或的特性为:
a^a=0;
0^a=a;
我们只需要将数组里面所有的数都弄进去,其他数字都是成双的,都会变成0,如数组{1,2,3,4,5,1,2,3,4},全部异或就为1^1^2^2^3^3^4^4^5就等于5啦
代码如下
int main()
{
int arr[] = { 1,2,3,4,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int dog1 = 0;
for (i = 0; i < sz; i++)
{
dog1 =dog1 ^ arr[i];
}
printf("dog1 = % d", dog1);
return 0;
}
我们继续上点难度,2只单身狗,一只舔狗,一只自律哥, 2个及多个单身狗数主要通过2进制的差异来进行左移将数组分类,从而找出它们,列如5和7,
5 二进制为 0101 (前面省略28个0)
7 二进制为 0111
它们差异在二进制第二位上,分别是0和1,那么我们左移1位&1,如果等于1,那就是7,如果等于0,那就是5,而其他左移1位&1的数字都是成对出现,进去后异或就抵消了,也就把5和7找出来了
代码如下
#include <stdio.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 7 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int dog1 = 0;
int dog2 = 0;
for (i = 0; i < sz; i++)
{
if ((arr[i] >> 1 & 1) == 1)
{
dog1 ^= arr[i];
}
else
{
dog2 ^= arr[i];
}
}
printf("%d %d", dog1, dog2);
return 0;
}
5和6也是同理
5 0101
6 0110
同样是左移一位就可以分开,把代码中的7改成6就ok
那么根据这个原理,理论上多个单身狗数都可以打印,我们再加一个数,5 7 12
int arr[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 7,12 };
5 0101
7 0111
12 1010
这里建议先解决12,它最好找,先解决7的话,12也会进入7的异或条件里面,所以先解决这个大的,左移3位&1等于1,然后再区别5和7,通过左移一位&1
代码如下
int main()
{
int arr[]={1, 2, 3, 4, 5, 1, 2, 3, 4,7,12};
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int dog1 = 0;
int dog2 = 0;
int dog3 = 0;
for (i = 0; i < sz; i++)
{
if ((arr[i] >> 3 & 1) == 1)
{
dog3 ^=arr[i];
}
else if((arr[i]>>1 & 1)==1)
{
dog2 ^= arr[i];
}
else
{
dog1 ^= arr[i];
}
}
printf("dpg1=%d dog2=%d dog3=%d", dog1, dog2,dog3);