1、异或介绍
我们知道,异或是通过比较二进制位的值,相同位0,不同为1
,根据此特性,我们可以发现以下规律:
- 结合律 (a ^ b) ^ c = a ^ (b ^ c);
- 交换律 a ^ b = b ^ a;
对于一个数a来说:
- 异或自己的结果为0:a ^ a = 0;
- 异或0的结果还是自己本身:a ^ 0 = a;
- 异或-1的结果为自身的值按位取反值:a ^ -1 = ~a
- 异或1的结果有两种:
- 如果本身是奇数,那么异或1之后得到的结果必然为偶数;
- 如果本身是偶数,那么异或1之后得到的结果必然为奇数
- 两个数异或的结果去异或其中一个数,其结果一定是另一个数
2、异或的简单使用
根据以上结论,我们来简单的做几个题测试一下它的作用。
- 第一题:使用异或判断一个数的奇偶性
题目分析: 根据前面的结论,异或1的结果只有两种,要么为奇数,要么为偶数;由这一结论我们可以让当前数异或1之后的结果去取余2,就能得出结果。
public static void main(String[] args) {
int num = 8;
if((num^1)%2==0){
System.out.println(num+"是奇数");
}else{
System.out.println(num+"是偶数");
}
}
- 第二题:不使用第三方变量交换两个数
题目分析: 根据前面的结论,两个数异或的结果去异或其中一个数,其结果一定是另一个数由此我们可以得出:
int n1=8,n2=4;
System.out.printf("交换之前:a=%d,b=%d\n",n1,n2);
n1 = n1^n2;//12
n2 = n1^n2;//8
n1 = n1^n2;//4
System.out.printf("交换之后:a=%d,b=%d",n1,n2);
- 第三题:找出1-1001中唯一成对的数,不能使用辅助空间,每个数据只能访问一次
题目分析: 根据前面的结论,异或自己的结果为0,异或0的结果为自己,所以我们只需要异或1-1001,再拿这个结果去异或1-1001包含重复数据的数
//定义数组的长度
int N = 11;
//初始化数组
int arr[] = new int[N];
//初始化数组元素 0-9 (value:1-10)
for(int i=0;i<arr.length-1;i++){
arr[i]=i+1;
}
//为最后一个元素随机赋值 10 value:random
arr[arr.length-1] = new Random().nextInt(N-1)+1;
//随机获取一个下标
int index = new Random().nextInt(N);
int x = 0;
for(int i=1;i<N;i++){ // 0-10
System.out.println(x+"^"+i+"="+(x^i));
x ^= i;
}
for(int i=0;i<N;i++){
System.out.println(x+"^"+arr[i]+"="+(x^arr[i]));
x ^= arr[i];
}
System.out.println(x);