单身狗问题(初级)兼(升级版)

文章通过两个编程题目介绍了如何使用位运算中的异或操作来解决数组中出现次数为奇数的数字问题。初级问题是一数组中只有一个数字出现一次,通过按位异或所有元素可找到该数字;升级问题则是有两个数字各出现一次,通过异或结果和位移操作能区分这两个数字。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所属专栏:经典算法题❤️
🚀 >博主首页:初阳785❤️
🚀 >代码托管:chuyang785❤️
🚀 >感谢大家的支持,您的点赞和关注是对我最大的支持!!!❤️
🚀 >博主也会更加的努力,创作出更优质的博文!!❤️
🚀 >关注我,关注我,关注我,重要的事情说三遍!!!!!!!!❤️

1.初级单身狗

1.1题目描述

一个数组中只有一个数字是出现一次,其他所有数字都出现了一次。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4
只有5出现一次,找出这个数。

1.2解题思路

  • 仔细思考我们发现,相同的两个数发生按位异或后就会等于0,就相当于消消乐一样,二0异或任何数都是本身,通过这个特性我们就很快可以得到解题思路了。

  • 首先第一步,我们初始化一个变量int x=0;我们用x按位异或数组中每个元素
    然后,我们将得到的结果在赋值给x,
    最后等到这个数组遍历完后,最终x的值就是单身狗。

  • 但是这个时候就有人会疑问,我们遍历数组的时候,元素是随机的,没办法得到相邻的相同的两个数之间按位异或然后消除掉啊。拿着怎么办。其实这个不必担心,因为这个按位异或你可想象成是多个数进行相乘,二乘法是符号交换律的,同样的按位异或也符合交换律这一特点,所有无论这两个相同的数位置在哪里,只要他们相同就一定会相互消除。

1.3代码实现

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

2.升级单身狗

2.1题目描述

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4,6
只有5和6只出现1次,要找出5和6.

2.2解题思路

如果我们接着上一题的思路的话,我们得到是两个单身狗异或后的结果。于是我们承接着上一题的思路,从这两个单身狗异或后的到的结果思考。我们知道,相同的两个数他们的二进制位都是对应相同的,要么是1要么是0,于是我们就可有从这一特点出发。既然我们无法通过直接异或得到结果,我们就想办法把这两个单身狗分别分成两派,把他转换成你只有一个单身狗的情况,就按照0/1分配,这个时候这两个单身狗异或后得到的结果派上用场了。异或的特点就是相同为0,相异为1,如果我们把异或后得到的结果通过右移并且按位与上1,如果这个结果是1的话,那么就说明右移的位数就是这两个单身狗二进制位不同的地方一个是1另一个是0,然后我们既然右移的位数,通过0和1把他们区分成两队,这个时候就转换成了只有一个单身狗的情况了。

2.3代码实现


#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
	int x = 0;
	int i = 0;
	//先找到两个单身狗异或之后得到的结果。
	for (i = 0; i < 10; i++)
	{
		x ^= arr[i];
	}
	//通过异或之后的结果找到第一个不同的二进制位
	int count = 0;
	while (((x >> count)&1)==0)
	{
		count++;
	}
	int a = 0;
	int b = 0;
	//通过右移,按照不同的位分成两类,转换成一个单生狗的情况
	for (i = 0; i < 10; i++)
	{
		if (((arr[i] >> count)&1) == 0)
		{
			a^=arr[i];
		}
		else
		{
			b ^= arr[i];
		}
	}
	printf("%d %d", a, b);
	return 0;
}
评论 52
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三问走天下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值