1.问题描述
当我们拥有一对数组
数组中只有一个数字是出现一次(单身狗),其他所有数字都出现了两次。
编写一个函数找出这个只出现一次的数字。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4
只有5出现1次,要找出5这只单身狗。
2.解决方案
2.1:暴力求解
我们可以直接遍历整个数组两次,只出现的数组记录出来,这样就可以算出只出现过一次的数组了。
#include <stdio.h>
void find_single_dog1(int arr[], int sz)
{
for (int i = 0; i < sz; i++)
{
int floag = 2;
for (int j = 0; j < sz; j++)
{
if (arr[i] == arr[j]) //当两次遍历会出现的相同时计数加一
{
floag--;
}
if (floag == 1&&j==sz-1) //当第二次遍历到最后一个数组这个数字还是只出现一次
{
printf("%d", arr[i]);
}
}
}
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4};
int sz = sizeof(arr) / sizeof(arr[0]);
find_single_dog1(arr, sz);
return 0;
}
5
2.1:方案优化(异或)
如果我们认识异或(^)这个符号的话我们可以知道:
二进制位:
- 相同为0
- 相异为1
所以我们可以知道当一个数异或自己为0
当一个数异或0时就不变
int main()
{
int a=5;
printf("%d\n", a ^ 0);
printf("%d\n", a ^ a);
return 0;
}
5
0
这样当我们把这些出现两次的数字异或起来,那么最后变成了0,再异或一次我们的“单身狗”,就可以得出我们单身狗的数值。
所以我们可以把代码优化为这样,将数组遍历一次就够了,再进行异或:
void find_single_dog1(int arr[], int sz)
{
int ret = 0;
for (int i = 0; i < sz; i++)
{
ret = ret ^ arr[i];
}
printf("%d", ret);
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4};
int sz = sizeof(arr) / sizeof(arr[0]);
find_single_dog1(arr, sz);
return 0;
}
5
3.题目升级
当我们拥有一对数组
数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4,6
只有5和6只出现1次,要找出5和6.
如果还是将所有的数异或起来,那么最后得到数就为5^6的结果,这样我们无法正确得出结果
3.1:分组讨论
使用数字异或做不到,那么我们感觉根据分组把两个需要异或的数字分开,并且每个相同的数字也在同一个组,这样分组异或就可以得出正确的结果
3.2:分组方法
既然要分组那么我们就要找出5和6的区别,当我们从二进制上看来看,5的二进制(101)和6的二进制(110)我们可以发现在第二个二进制中一个是1 一个为0,利用这个特征,我们就可以也把数组其余的数按这种分类方法分为(1 1 3 3 5) (2 2 4 4 6)
3.2:代码实现
既然涉及到了二进制位置,我们想起移位操作符,就可以知道,我们将数向右移动一位,再判断是否为1或0就可以实现代码了。
void find_single_dog2(int arr[], int sz)
{
int ret = 0;
for (int i = 0; i < sz; i++)
{
ret = ret ^ arr[i];
}
//分组
int dog1 = 0;
for (int i = 0; i < sz; i++)
{
if ((arr[i] >> 1) & 1 == 1)
{
dog1 = dog1 ^ arr[i];
}
}
int dog2 = ret^dog1; //dog1已经得出为6 再让他异或5^6(6^5^6)得到的数就为5
//int dog2 = 0;
//for (int i = 0; i < sz; i++)
//{
// if ((arr[i] >> 1) & 1 != 1)
// {
// dog2 = dog2 ^ arr[i];
// }
//}
printf("%d %d", dog1, dog2);
}
int main()
{
int arr[] = { 1,2,3,4,5,6,1,2,3,4 };
int sz = sizeof(arr) / sizeof(arr[0]);
find_single_dog2(arr, sz);
return 0;
}