用‘^‘找出你身边的单身狗


在这里插入图片描述

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拆分
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/009d6d61ae3e4aabac5c64349838f6da.png在这里插入图片描述

单身狗5

	int a[] = { 1,1,4,4,5 };
	int len = sizeof(a) / 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;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值