【异或】在一组数中,两种数出现了奇数次,其他数出现了偶数次

异或运算
0 ^ 0 = 0,1 ^ 1 = 0,0 ^ 1 = 1; 相同为0,不同为1
异或运算满足交换律和结合律
c =a ^ b =b ^ a
c =( a ^ b )^ c = a ^ ( b ^ c )
所以
a^b ;
a ^ b ^b=a;
a ^ b ^a=b;
如果是一个数组里一个数出现奇数次,那么对这个数组从头到尾异或,最终的等于的是出现奇数次的数, 因为偶数次的数在异或之后都等于0了 。

如果是一个数组,两种数出现了奇数次,其他数出现了偶数次;

假设奇数次的数为 a,b;定义一个变量,对数组从头到尾异或,最终的结果是eor=a^b;

int eor = 0;
	
	for (int i = 0; i < l; i++)
	{
		eor ^= a[i]; //异或之后eor=a^b
	}

那怎么分开ab;
因为a和b是不同的两个数,所以eor一定不等于0;所以异或之后eor至少有一位为1;假设eor的第八位是1,那么a和b的第八位一定是不相同的
例如,eor=2 ^ 3 ;
00000010
00000011
-------------
00000001 = eor
eor=2^4;
00000010
00000100
-------------
00000110 = eor
随便取到一位数为1的,可以通过这个位置区分数组中的元素,分别是在这个位上为1的和0的两种类型。
例如,分成第八位是1和第八位是0的数,a,b的第八位一定不同,所以两个数被分到不同阵营里。

此时再定义一个变量,对其中一个阵营里的数再异或,偶数次数的依旧为会异或为0,而异或的结果则为a或b中的一个,比如这个数是a,将它与eor异或之后就能得到b,(eor=a^b);
关于取到最右边是1的那一位:
~eor 取反
~eor + 1 取反加一
eor & (~eor + 1)
在这里插入图片描述

void TimesNum(int a[], int l)
{
	int eor = 0;
	
	for (int i = 0; i < l; i++)
	{
		eor ^= a[i];
	}
	int right = eor & (~eor + 1);//取到最右边一位1
	int onlyOne = 0;
	for (int i = 0; i < l; i++)
	{
		if ((right & a[i])==0)//&运算:同为1才等于1,判断等于0是将对这个位上是0的数异或
		{						//也可以==1,是将对这个位上是1的数异或
			onlyOne ^= a[i];
		}
	}
	int nu = eor ^ onlyOne;
	cout << onlyOne << " " << nu << endl;
	
}

:左程云老师的课

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值