学习了位操作符后,我就在脑子里想:那这些操作符可以用来干什么呢?
能否像三目操作符一样简洁高效地简化代码呢?
今天,它来了,我将结合leetcode例题阐述位操作符的用法。
一. &的性质
首先根据规则,显然有以下规律
a&a=0
假设a=15
0000000 00000000 00000000 00001111
0000000 00000000 00000000 00001111
显然,其可以用于判断两个数是否相等。至于还有其他用法,大概是和其他位运算结合使用,大家下去可以自己尝试一下,这里不做重点讨论。
& 还有些其他用法:
在一些特殊题目中可能会用到
二. ^的性质
1.N^0=N
2.N^N=0
3.a^b=b^a
4.(a^b)^c=a^(b^c)
知道这些性质后我们就可以完成一些有趣的操作
如: 如何不使用中间变量交换两个数?
正常情况下:
int temp = a;
a= b;
b= temp;
使用^进行:
a=a^ b;
b=a^ b;
a=a^b;
即:
但这样会使代码可读性变差,一般不推荐使用,只用与特殊的题目中。
正文开始:
显然通过0与数组全部异或后结果就是只出现一次的数字
int ret = 0;
for (int i = 0; i < numsSize; i++)
{
ret ^= nums[i];
}
那么,如果出现两个及以上的不同的数字该如何解决呢?
如果我们能把这两个数字分开变成上一题那种情况就可以继续按照这个思路进行下去了
假设数组中元素为A.A.B.B.C.C.D.D.E.E.F.F.X.Y
那么把数组分成这样我想大家一定会了
为了解决这个问题: 把这两个数字分开
首先先了解:如何获取一个数字最右侧的1?
公式:a&(~a + 1)也就是a & -a
a 1010
-a 0110
a&-a 0010
这样就得到了a最右侧的1。
接下来的步骤:
1.先将所有元素异或,K=X^Y^....,K≠0
K一定不是0(因为XY不相等)
2.K’= K &(~K + 1)
K’是K最右侧的1,这样XY在这个位上一定不同(称这个位是第n位)
3.将数组中的数字分为两组
分组依据:第n位是0一组,第n位是1一组,X和Y必在不同组
假设:A&K’=0 D&K’=1 ... 分别放在不同数组中
4.X=第一组元素全部异或
得到X
5.Y =K^X