一个、两个单身狗/只出现一次的数

文章讲述了如何利用异或操作在数组中查找出现一次的数字,以及扩展到查找出现两次的两个数字。通过位操作区分单身数字和成对数字,提供C语言代码示例。
摘要由CSDN通过智能技术生成

一个单身狗

题目:一个数组中只有一个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这个只出现一次的数字。

例如:

有数组的元素是:1,2,3,4,1,2,3,4,5

只有5只出现1次,要找出5。

在成对的数中找到一个单独的,首先我们要了解位操作符 ^ (异或),如果操作数二进制位相同则为0,相异则为1,那让我们想象一下,如果一个数和它自己异或,或者和0异或结果是多少呢?

由图我们不难看出,一个数和它自己异或的结果是0,如果和0异或的话结果是它本身。

a ^ a = 0;
a ^ 0 = a; 

所以这道题我们可以使用异或来解决,成对的数异或结果自然会是0,最后只剩单身狗与0异或得到它本身。代码如下:

#include<stdio.h>
int main()
{
	int arr[9] = { 1,2,3,4,1,2,3,4,5 };
	int tmp = 0;
	for (int i = 0; i < 9; i++)
	{
		tmp ^= arr[i];
	}
	printf("%d", tmp);
	return 0;
}

两个单身狗

如果数组中只有一个单身狗是很好找出来的,但是如果数组中有两个单身狗呢?我们应该怎么找出来?显然简单的异或我们只能得到两个单身狗异或的结果,我们还是要将成对的数异或掉,再想办法把两个单身狗分开异或。

题目:一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这两个只出现一次的数字。

例如:

有数组的元素是:1,2,3,4,5,1,2,3,4,6

只有5和6只出现1次,要找出5和6。

首先我们要将两个单身狗分开,两个单身狗异或的结果肯定不会是0,找到两个单身狗异或后为1的位数,这样我们就可以把两个单身狗分开,也可以将剩下成对的数分在一起,因为成对的数二进制的每个位数一定相同。

如图,第一步将所有数异或得到两位单身狗异或的结果,找到结果中为1是第几位,用这一位将两位单身狗分到不同的两个组,然后再让num1和num2分别异或就可以得到两个单身狗。代码如下:

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,1,2,3,4 };
	int num1=0;
	int num2=0;
	int tmp = 0;
	for (int i = 0; i < 10; i++)
	{
		tmp ^= arr[i];//tmp就是两个单身狗异或的结果
	}
	int k = 0;
	for (int j = 0; j < 32; j++)
	{
		if (((tmp >> 1) & 1 )!= 0) //找出tmp里为1的位数
		{
			k = j;//第k位为1
			break;
		}
	}
	for (int i = 0; i < 10; i++)
	{
		if (((arr[i] >> k) & 1) != 0)//第k位为1的异或
		{
			num1 ^= arr[i];
		}
		else//第k位为0的异或
		{
			num2 ^= arr[i];
		}
	}
	printf("%d %d", num1, num2);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值