栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 利用 异或 求出现奇数次数字

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 利用 异或 求出现奇数次数字

1:数组中只有一个数字出现了奇数次,其余数字出现偶数次,找出这个出现奇数次的数字。

2:数组中有两个数字出现了奇数次,其余数字出现偶数次,找出这两个出现奇数次的数字。

出现如上两种问题或类似问题可以使用 异或的思想求解 ,在使用之前,先了解异或的几种基本性质
1)a ^ b ^ c=a^c ^b 即异或满足交换律,
2)a^ a=0 一个数异或它本身得到的结果为0
3)a^ 0=a 一个数异或0还是等于它本身

很好用来理解异或的例子是 你可以将异或理解为无进位相加:
如:10111^10011=???

10111
^
10011
=00100
也就是如果能够进位,直接将那位写成0就行了,进到前面的1不用管。

ok,有了上述理论基础可以开始解决问题了:

1 在这里插入代码片,

int a[5] = { 0,0,1,1,3 };
int arb = 0;
for (int i=0; i<5; i++)
{
    arb = arb ^ a[i];
}

cout << arb;

解析:因为一个数异或它本身是为0的,所以出现偶数次的数都可以消掉,最后只剩下一个出现奇数次的数字,即为所求值。

2在这里插入代码片,

int arr[8] = { 0,0,1,1,2,3,4,4 };
int arb = 0,other=0;
for (int i=0; i<8; i++)
{
    arb ^= arr[i];//最后求出的值为2异或上3
}
int rightone = (~arb+1)& arb;
for (int i : arr)
{
    if ((rightone & i) == 0)	//等于0或者rightone都可以,分出了两种数,一种对应位为1,一种对应位为0
        other ^= i;
}
int another = other ^ arb;
cout << other <<" "<< another;

解析:和第一题一样,这道题是求两个奇数次数字,将整个数组的数进行异或,最后得到的值arb为两个奇数次数字异或起来的值,也就是arb=奇数次1数字 ^ 奇数次2数字,接下来需要把这两个数字分开,
只需要再求出其中一个,就能得到另一个,此时引入了&号和~号。

~:取反 如10110 取反为 01001
&:同为1为1,否则为0,10100&11001==10000 101&101=101

因为arb不为0(a不等于b),所以二进制数字中总有一个位置上为1 ,所以a或者b在该对应位置上不相同,一个为1,一个为0,rightone的作用是取出arb二进制数中的最后出现的一个1

假如arb=10110,~arb=01001 (~arb+1)=01010 两者相&得到00010,取出了最后位数的1,若是以后遇到需要取出右边的1时,请直接 取反加1 再 相与&

取出最后的1的作用:利用这个1来分出那个对应位置上为1的数字,这些数字中其中必包含一个我们需要求的奇数次数字a或者b,另一批对应位置为0的数字必包含另一个我们需要的奇数次数字。

所以other最后就是a或者b中的其中一个,再用other ^ arb即可求出另外一个即可

																(暂完结)

可以思考下出现三个奇数时有什么方法解,后续会将文章配上图更好的阅读,嘿嘿,重走一回编程路,

`

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/510830.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号