给大伙整整面试中常见的单身狗问题,由于学习还不够,就说说一条到三条的情况吧;
一条单身🐕
这是最简单的,可以通过遍历数组和异或解决;
遍历
遍历数组方法相对麻烦一点,需要遍历每个元素,将数组进行排序,然后相邻两个继续比较,相同就跳过这两个元素,直到找到那个🐕;
具体如下:
排序方法多种多样,冒泡排序比较经典,也可以用qsort快速排序,看个人喜好。
异或
异或的方法相对快很多,直接将数组从前往后异或就能找出来了,两个相同的数异或结果为0,整个数组异或下来的结果就是🐕;
具体如下:
相比之下,简洁了很多。
两条单身🐕
两条单身狗也是用异或的方法,但是异或出来的结果是两条单身🐕的值,这就要想办法分开了,找到异或结果中一个位为1的位,记录下这个位置二进制位为1的数,这就将数组分类了,再将记录下来的数字进行异或就能找到单身🐕了,有位为1的位就会有位为0的位,同样的道理,另一条🐕也就出来了;
具体如下:
#include<stdio.h>
#include<stdlib.h>
void finddog(int a[], int n, int* dog)
{
int i = 0;
int pos = 0;
int ret = 0;
//遍历数组,找到结果为两个不同数的异或
for (i = 0; i < n; i++)
{
ret ^= a[i];
}
//寻找这两个不同数异或结果的第一个位为1的的位
for (pos = 0; pos < 32; pos++)//整型32位,从低位向高位依次遍历
{
if (((ret >> pos) & 1) == 1)
{
break;//pos记录二进制位为1的数
}
}
for (i = 0; i < n; i++)
{
//找到数组中pos位为1的数,进行异或
if (((a[i] >> pos) & 1) == 1)
{
dog[1] ^= a[i];
}
//找到数组中pos位为0的数,进行异或
else
{
dog[0] ^= a[i];
}
}
}
int main()
{
int dog[2] = { 0 };
int arr[] = { 1,2,5,8,9,5,2,1};
int sz = sizeof(arr) / sizeof(arr[0]);
finddog(arr, sz, dog);
printf("dog1:%d\ndog2:%d\n", dog[0], dog[1]);
return 0;
}
如果上面这个觉得不够理解可以看下面这个:
#include<stdio.h>
int main()
{
int x1 = 0, x2 = 0; //两条单身狗
int pos = 0; //寻找两个单身狗异或后第m位为1
int ret = 0;//存储两个单身狗异或后的值
int arr[] = { 1,2,5,8,9,5,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
ret ^= arr[i];//ret为数组中的数异或的结果就是单独的7^9
}
//printf("%d\n",ret);//打印只有一只单身狗时
//从数组分离7^9
//找到ret = 7^9二进制中第m位为1
//就是7和9二进制中第pos位一个为1一个为0
//然后从数组中将他们分成两组
//一组第pos位为1,一组第pos位为0
//最后成对的都被抵消,剩下的就是单身狗
while (pos < 32)
{
if (ret & (1 << pos))
{
break;
}
else
{
pos++;
}
}
for (i = 0; i < sz; i++)//找到二进制位第一个1
{
if (arr[i] & (1 << pos))
{
x1 = x1 ^ arr[i];//第pos位为1的异或在一起
}
else
{
x2 = x2 ^ arr[i];//第pos位为0的异或在一起
}
}
printf("%d,%d", x1, x2);
return 0;
}
三条单身🐕
三条单身🐕的思想和两条🐕类似,也是分类异或,分成一组有两条单身🐕和一组有一条单身🐕,然后
像上述方法就能找出来了,这里我就不放代码了,大伙自己试吧!