目录
一、寻找一个单身狗
1.题目描述
一个数组中只有一个数字只出现一次,其他所有数字都出现了两次,请找出这一个只出现一次的数字。
2.思路解析
首先面对此类问题,我们首先想到的是用循环的方式一个一个找出来,并记录其出现的次数,从而找出只出现一次的数字。但今天我们有更巧妙的办法!———异或
异或^——相同为0,相异为1。我们利用异或的此性质,出现两次的数字异或为0,那么将所有的数字异或的结果岂不就是出现一次的数字吗!单身狗不就找到了!!!
3.代码实现
#include<stdio.h>
int Find_dog(int arr[], int n)
{
int a = 0;
int i = 0;
for (i = 0;i < n;i++)
{
a ^= arr[i];
}
return a;
}
int main()
{
int arr[] = { 1,2,3,1,2 };
int num = Find_dog(arr, 5);
printf("单身狗为%d\n", num);
return 0;
}
运行结果:
单身狗为3
二、寻找两个单身狗
1.题目描述
一个数组中有两个数字出现一次,其他所有数字都出现了两次,请找出这两个只出现一次的数字。
2.思路解析
前面我们用异或的方式找到了一个单身狗,那我们能否也用异或的方式找到两只单身狗呢?
答案是可以的!!但是如果我们像前面一样将全部数字异或,得到的是两个单独的数字的异或值,那好像得不到我们的结果,但是如果我们将这一组数字分为两组呢,再分别异或,那不就得到了嘛。
3.代码实现
我们来理一理思路啊,以这组数据为例
{1,2,3,4,5,1,2,3,4,7}
首先我们要将这组数据分为两组,如何将两只单身狗放在不同的组里呢?将5和7异或,得到的值的二进制位肯定至少有一位为1,相同为0,相异为1,所以5和7在此二进制的位置必然是一个为0一个为1,那我们就将所有数字此二进制位为0的分为一组,为1的分为一组,再分别异或,单身狗就找到了。
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,7 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int ret = 0;
for (i = 0;i < sz;i++)
{
//所有值异或,其实就是5与7的异或值
ret ^= arr[i];
}
//找到异或值二进制位为1的位置,将0分为一组,1为一组
//并找到ret第几位为1
int pos = 0;
for (i = 0;i < 32;i++)
{
if (((ret >> i) & 1) == 1)
{
pos = i;//第pos位为1
break;//找到之后立马跳出来
}
}
//开始分组,arr[i]的pos位为1为一组
int num1 = 0;//放1
int num2 = 0;//放0
for (i = 0;i < sz;i++)
{
if (((arr[i] >> pos) & 1) == 1)
{
num1 ^= arr[i];
}
else
{
num2 ^= arr[i];
}
}
printf("%d %d", num1, num2);
return 0;
}
运行结果 :
5 7