关于我用异或让数组里的2条单身狗现形这件事

1.什么是数组里的单身狗

  假定有这么一个数组,数组里的整数都成双成对,却有两个数字是单身数。

例如:int arr[10]={1,2,3,4,5,1,2,3,4,6};中的5和6便是单身数,该怎么找到它们?

2.^异或是什么?

  按位异或的概念是指,对两个整数的二进制进行比较,若对应位数相同则为0,相异则为1。

例如:3的二进制为000....0011,而5的二进制为000....0101;则3^5的二进制为000....0110,值为6。

3.为什么说异或可以揪出单身狗?

如果用成对的情侣数,例如两个5对ret=0进行异或,(0101)^(0000)=(0101)---->(0101)^(0101)=(0000);

可见,对ret进行两次同一数值的异或,会使ret的值回到原值,而如果中间穿插一个单身数6:

(0101)^(0000)=(0101)---->(0101)^(0110)=(0011)---->(0011)^(0101)=(0110)=6;

最后ret的结果就为6这个单身数。

4.具体该怎么实现?

1.首先让所有整数与ret异或一遍,求出两个单身数的异或融合;

2.求两个单身数在第i个二进制位上是相异的,通过这个i,可以将两个单身数分开;

3.将第i位为1的数字分开出来与0逐个异或,就可以求出第一个单身数;

4.由于ret是两个单身数的异或融合,很容易通过第一个单身数求出第二个单身数。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int ret = 0, i, j, single1 = 0, single2 = 0;
	for (i = 0; i < sz; i++)
		//将所有数字都与ret逐一异或,如果为两个相同的数,那么和ret产生的异或效果将会抵消
	{
		ret ^= arr[i];//最后ret的值将是两个单身数的异或结果
	}
	for (i = 0; i < 32; i++)
	{
		if (((ret >> i) & 1) == 1)//再求出ret的最后的为1的位数,该位为1说明两个单身数的二进制码在此位相异
			break;
	}
	for (j = 0; j < sz; j++)
	{
		if (((arr[j] >> i) & 1) == 1)//通过位操作符和按位与操作符,可以将数组中此位为1的数筛选出来
		{
			single1 ^= arr[j];//此时进入到这里的数为成对的非单身数和其中一个单身数,经过相同逻辑的遍历异或,就可以求出single1
		}
	}
	single2 = ret ^ single1;//再将single1与ret异或,取出single2
	printf("%d %d\n", single1, single2);
	return 0;
}

总结:通过这道题,我们可以了解到,每一处语法的设计都有其独到之处,学习c语言,也是深入研究语法并通过固定的规则开辟出多样的解决问题的路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值