异或运算总结
今天我们一起来聊聊异或运算:
定义:
异或,是一个数学运算符,英文为exclusive OR,缩写为xor,应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。
异或也可以看成是不带进位的加法,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位。
异或运算的作用
1.参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。
即:
0^0 = 0,
1^0 = 1,
0^1 = 1,
1^1 = 0
2.使用异或交换两个数,在冒泡排序、选择排序等众多的排序算法中,都会涉及到两个数值的交换,一般做法是利用空间,这样的话,效率就会大大的降低,使用异或可以解决空间问题。但是需要注意的是:使用亦或操作必须要保证的是内存地址不能相同,如果某一个数组有相同的指向,那么亦或完了之后所得结果会是0。
a = int[a] ^ int[b]
b = int[a] ^ int[b]
a = int[a] ^ int[b]
3.面试题:已知在一个数组中:只有一种数出现了奇数次,其他的都是偶数次;有两种数出现了奇数次,其他都是偶数次。分别找到这个数以及这两个数。
分析思路:其实第一问是很好想到的,对数组中所有的数都进行亦或操作,由于除了这个数的其它数都是偶数个,那么由于亦或操作的结合律(亦或操作还具有交换律),所有的偶数所得结果为0,那么此时就是0^这个数,最终就是所求的数。具体代码:
public static void printOneNums(int[] nums){
int xor = 0;
for (int num : nums) {
xor ^= num;
}
System.out.println(xor);
}
第二问:所有的数异或得到所求的两个数a^b,又知道a!=b,那么必然有一位上不是0,(可以求最右边的为1的数:rigthOne = xor & (~xor + 1))(原因在下面),设变量xor1 ,让数组中所有那一位为0或者为1的数进行异或运算,得到的就是a或者b,那么另一个数字就是xor^xor1。
public static void printNum2(int[] nums){
int xor = 0;
for(int num: nums) {
xor ^= num;
}
int rirhtOne = xor & (~xor + 1);//找到最右边为1的数
int xor1 = 0;
for(int cur: nums){
if((cur & rirhtOne) == 1){ //筛选出那一位上为1或者0的数
xor1 ^= cur;
}
}
System.out.print("第一个数:"+xor1+",第二个数:"+ (xor ^ xor1));
}
}
结尾:
纯属记录自己的学习过程,如果有错误,欢迎指出,一起进步。