
1.单身狗1.0
题目内容
在一个整形数组中,只有一个数字出现一次,其他数字都是成双成对出现的,请找出那个只出现一次的数字。
例如:
数组中有:1 2 3 4 5 1 2 3 4,只有5出现了一次,其他数字都出现两次,找出单身狗5.
思路分析:
根据位操作符异或(‘^’)两整形的二进制位的对应位相等为零相异为一原则
因此我们可以将数组内的所有元素进行异或
代码实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string>
int main()
{
int i,n=0;
int a[] = { 1,2,3,4,5,4,3,2,1 };
int len = sizeof(a) / sizeof(a[0]);//计算数组长度
for (i = 0;i <len ;i++)//遍历数组
{
n ^= a[i];//将数组内元素全异或
}
printf("%d", n);
return 0;
}
2.单身狗2.0
题目内容
在一个整形数组中,有两个数字出现一次,其他数字都是成双成对出现的,请找出那个只出现一次的数字。
例如:
数组中有:1 2 3 4 5 1 2 3 4 6,只有5,6出现了一次,其他数字都出现两次,找出单身狗5,6.
差别分析:
相比于单身狗1.0,两个单身狗暗箱操作,若直接异或,得出的结果是(5^6)=3,因此无法将单身狗5和6找出。
思路分析:
我们可以将单身狗2.0拆分为两个单身狗1.0
例如:我们将1 1 4 4 5放至一组所有元素异或找出单身狗5,再将3 3 2 2 6放至一组所有元素异或找出单身狗6.
中心思想:
将5 6拆分
 / sizeof(a[0]);//计算数组长度
for (i = 0;i <len ;i++)//遍历数组
{
n ^= a[i];//将数组内元素全异或
}
单身狗6
int a[] = { 3,3,2,2,6};
int len = sizeof(a) / sizeof(a[0]);//计算数组长度
for (i = 0;i <len ;i++)//遍历数组
{
n ^= a[i];//将数组内元素全异或
}
我们可以将数组内所有元素异或得到(5^6=3)根据异或的性质我们可以得知当3的二进制位为1时说明5和6的二进制位不相等,因此我们可以利用这个性质将5和6分开,随便取3中二进制位为1的数的位数作为特征点记作k,如果数组元素第k位等于1地话就和5归类为一组,否则和6归类为一组。
数组异或记作j
int a[] = { 1,2,3,4,5,1,2,3,4,6 };
int len = sizeof(a) / sizeof(a[0]);//计算数组长度
for (int i = 0;i < len;i++)
{
j ^= a[i];
}//将数组异或求出5^6存放至变量j
计算K
for (int i = 0;i < 32;i++)//遍历j的二进制二进制有32比特位循环32次
{
if (j & 1 == 1)//判断j二进制位是否为1
{
k = i;//将j的二进制位为1的位数存放至变量k
break;
}
j >> 1;
}
合并代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
int j=0,k;
int p1 = 0, p2 = 0;//单身狗p1,单身狗p2
int a[] = { 1,2,3,4,5,1,2,3,4,6 };
int len = sizeof(a) / sizeof(a[0]);//计算数组长度
for (int i = 0;i < len;i++)
{
j ^= a[i];
}//将数组异或求出5^6存放至变量j
for (int i = 0;i < 32;i++)//遍历j的二进制二进制有32比特位循环32次
{
if (j & 1 == 1)//判断j二进制位是否为1
{
k = i;//将j的二进制位为1的位数存放至变量k
break;
}
j >> 1;
}
for (int i = 0;i < len;i++)
{
if ((a[i] >> k)&1 == 1)//判断数组其他元素第k位是否为1
p1 ^= a[i];
else
p2 ^= a[i];
}
printf("p1=%d,p2=%d", p1, p2);
return 0;
}