提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
例如:异或、与、取反等在算法题中可作为高效的一种运算手段解决某些算法问题
`提示:以下是本篇文章正文内容,有两个算法题做参考
一、异或运算,在二进制上相同数异或为0,不同数异或为1
1.一堆数组,只有一个数出现奇数次,找到这个数?
示例:数组{1,2,3,1,2,3,5,5,5},我们要最终通过代码找到只出现奇数次的数5
代码如下(示例):
/**
* 一堆数组,只有一个数出现奇数次,找到这个数
*/
public class Demo1 {
/**
* 异或相同的为0 不同的为1
* 那么所有的数异或出来的值就是出现奇数次的这个数
*/
public static void main(String[] args) {
// 0异或所有不是本身的数为那个数
int temp = 0;
int [] arr = new int[]{1, 2, 3, 1, 2, 3, 5};
for (int cur : arr) {
temp ^= cur;
}
System.out.println(temp);
}
}
2.一堆数组,只有两个数出现奇数次,其余数出现偶数次,找到这两个数?
代码如下(示例):
/**
* 一堆数组,只有两个数出现基数次,其余数出现偶数次,找到这两个数
*/
public class Demo2 {
/**
* 异或相同的为0 不同的为1
* 1.所有数异或结果为a^b
* 2.又因为ab两个数不相同,所以在某一位上肯定不一样,一个为1,一个为0,按照这个划分可以划分为存在a,b的两个数组
* 3.把上面某一方数组异或结果为a或者b
* 4.再与1操作值异或得到另一个数
*/
public static void main(String[] args) {
// 得到a^b
int temp = 0;
// a或者b
int one = 0;
int [] arr = new int[]{1, 2, 1, 3, 1, 2, 1, 3, 5, 9};
for (int cur : arr) {
temp ^= cur;
}
one = temp;
// 取a^b二进制最右侧的1的数
int rightOne = one & (~one + 1);
for (int cur : arr) {
// 如果与运算结果为rightOne,则代表当前遍历的数在二进制上该位置为1
if ((cur & rightOne) == rightOne) {
one ^= cur;
}
}
System.out.println("一个数为:" + one);
System.out.println("另一个数为:" + (temp ^ one));
}
}
分析过程:
a = 5的二进制为0101
b = 9的二进制为1001
one = a^b为1100
~one = ~(a^b)为0011
~one + 1 = ~(a^b)+1为0100
one & (~one + 1) = (a^b) & (~(a^b) + 1)为0100
也就是说通过第三位为1或者0把数组分成了两个阵营,a,b肯定分别存在不同的阵营,遍历的数跟rightOne与运算如果等于rightOne那么该数在二进制上第三位肯定为1,最后把所有此特性的数异或运算得到的就是a或者b,那么另一个数只要再异或一次就行
比如temp=a ^ b、 one=a、temp ^ one = a ^ b ^ a=b
总结
以上就是今天要讲的内容,本文通过两个算法题简单介绍异或在运算中的一些运用,喜欢的小伙伴点赞收藏