使用异或^找出数组里面只出现了一次的一个or俩个or多个数(具体几个是已知数据)

先补充一些异或的基础知识,以及如何得到一个数的最低位是1的方法

异或的基础知识:

^按位异或

俩个二进制数相同的取0,不同的取1

运算遵循:

1 任何数和自身异或得到的是0

2 0和任何数异或的得到的是自身(自身指的是任何与0异或的数)【这种效应就像照镜子一样】

  • 异或满足交换律和结合律
  • x ^ x == 0
  • x ^ 0 == x

 附上前一篇文章链接(详细讲解按位异或):https://blog.csdn.net/plz_bb/article/details/120837620?spm=1001.2014.3001.5501

找出数组里面只出现了一次的一个数:

用它的相反数的补码和它的补码进行按位取与

解释如下:

该数自己的补码与其相反数的补码按位取与得到的二进制数最低位1的位置并不会改变(因为该数最低位为1后面全是0,它的相反数(负数)的补码会在1的基础上再加1,按位进,则会在0的位置(正数为最低位1的位置)变为1,所以并不改变最低位为1的位置)

举个例子:

如6=0000 0110,-6 = 1111 1001 + 1 = 1111 1010

最低位的1右边的0,在取反之后就会全部变为1,再加一,进位后,取反获取的1全部进位了,最低位的1又被进位上来了,即最低位的1保持不变。

找出数组里面只出现了一次的一个数:

将这些数分别异或^(要设定一个初始值为0,从0开始与第一个数异或)最后得到的是二进制数是只出现一次的那个数。

找出数组里面只出现了一次的俩个或者多个数:

分堆,再各自找。

先说找俩个的具体做法:

依次将这些数组进行按位异或^(设定一个初始值为0,从0开始与第一个数异或,先异或一对一对的配好的,最后将没有配对的数异或得到一个二进制数),然后找出该二进制数最低位是1的那一位(找法是:与它的相反数按位取与),然后再判断,与这一位的数相同的(都为1)就分为一组,不同的就分为另一组,就可以把原有的数分为2类,分开以后在每一个堆里各自进行异或,(类似于找出一个数的方法)就能找到该2个只出现一次的数了。

再说找多个的:

多个的最后会变成俩个,再运用俩个的找法具体细分。

即多变2变1,取异或。

原理:

1 异或的原理:0与任何数异或都等于任何数本身,与本身异或都为0,所以从0开始异或的时候,先得到的是本身,本身与又与相同的异或,又得到0,如此循环往复,最后到只出现一次的数进行异或,得到一个数(如果只有一个则为自己,如果有俩个或多个只出现一次的数则得出一个数)

2如何根据二进制数最低位1,将数分为俩(多)组,且俩(多)组分别只包含一个只出现一次的数?每一组只含一个出现一次的数可以这样理解:

因为本来该二进制数是这些只含有一个的数共同异或的得到的值,异或的值为1代表这俩个数在该位的值是各不相同的(一个为0另一个为1),所以可以分到俩个不同的组。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值