异或运算详解与练习
Posted 飞人01_01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异或运算详解与练习相关的知识,希望对你有一定的参考价值。
一、异或运算讲解
按位异或 / 同或
int main()
{
//按二进制位展开
//按位异或: 相同为0,不同为1
//按位同或: 相同为1,不同为0
int a = 10; //二进制: 0000 1010
int b = 6; //二进制: 0000 0110
int c = a ^ b; // 0000 1100
return 0;
}
同或相对来说,在面试中不会遇到,主要就是异或。两者的功能是相反的,容易记混淆,这里提供一个简单的记忆方法 :
“ 异或:按二进制位展开做加法不进位运算。”
例如: 上述代码:0000 1010 和 0000 0110 分别对应相加:
蓝色字体本应是 1 + 1 = 2,理应来说需要往高位进1,这里异或,则不进,直接余0即可。 其他 非蓝色字体 按照正常的加法运算后,写下来即可。
异或性质(重点):
n ^ 0 = n
n ^ n = 0
二、练习题
题目 | 链接 |
---|---|
计算数组中出现奇数次的数值 | 牛客网 |
二进制中1的个数 | 牛客网 |
计算数组中出现奇数次的数值
//例如数组: [3,2,3,3,2,2,2,5,7,9,7,5,9]
//数值3有3个,2有4个, 5、7、9 各有2个
如果这题直接暴力排序求解的话,就违背了面试官的初衷,也就是说这次面试凉了一大截了。
那么如何赢得面试官的青睐呢?不急往下看。
我们说了上面的异或性质,该怎么用呢。
想想,此题中出现的所有数据中,只有一个数据是出现了奇数次,其他的都是偶数次,那我们把所有的数据进行一个异或,最后异或的结果不就是那个奇数次的数值嘛。
注释: eor = 3 ^ 3 ^ 3 ^ 2 ^ 2 ^ 2 ^ 2 ^ 5 ^ 5 ^ 7 ^ 7 ^ 9 ^ 9 ;
划横线部分可以用 异或性质2 计算出 这一串都是0,化简为 eor = 3 ^ 3 ^ 3 ^ 0; 前面的 两个 3异或运算 后得到0 ,即就是说最后的式子化简为 eor = 3 ^ 0; 到了这一步不就是 异或性质1 吗? 最终结果就是 3 咯。
public static void main(String[] args) {
int[] arr = {3,2,3,3,2,2,2,5,7,9,7,5,9};
int eor = 0;
for (int i = 0; i < arr.length; i++) {
eor ^= arr[i];
}
System.out.println("eor: " + eor);
}
二进制中1的个数
按照常规的取模运算,这样的解题思路,是入不了面试官的眼的。只能换个思路解。还是位运算的角度求解。
直接上代码。
解法一:异或
public static void main(String[] args) {
int a = 10;
int count = 0;
while (a != 0) {
count++;
a = a ^ (a & ((~a) + 1));
//a & ((~a) + 1) 计算得到的是a二进制位中最右边的1
}
System.out.println("count: " + count);
}
这里特别需要讲解一下的就是这个 a & ((~a) + 1)
;
这样,我们就可以拿到10这个数在内存中最右边的 1 ;
最后再与a本身做 异或运算 ,就 ***“约”***掉了最右边的1;
这个算法思想a & ((~a) + 1)
,在以后刷题中,会应用到很多场景,各位小阔爱得深刻理解里面的奥妙哦。
解法二:与运算
public static void main(String[] args) {
int a = 10;
int count = 0;
while (a != 0) {
count++;
a = a & (a - 1);
}
System.out.println("count: " + count);
}
具体的算法思想,就留给大家自己动手画一画吧。
本期更新到此结束,如若觉得小编写的还可以,能够学到一些知识,还请点个赞哦,在此感谢啦!!!
下期见!!!
以上是关于异或运算详解与练习的主要内容,如果未能解决你的问题,请参考以下文章
Java的位运算符详解实例——与(&)非(~)或(|)异或(^)