一、按位异或
按位异或
(Exclusive OR,简称XOR
)是一种二元运算符,用于对两个二进制位进行比较。如果两个比较的位不同,则异或的结果为1;如果相同,则为0。
异或主要看重异,所以值不同时为1,值相同时为0,比较好记忆
1.1 异或的性质
- 一个数与自身做异或运算的结果是0
(x ^ x = 0)
。 - 一个数与0做异或运算的结果是它本身
(x ^ 0 = x)
。 - 异或运算满足交换律和结合律
(a ^ b = b ^ a 和 (a ^ b) ^ c = a ^ (b ^ c) )
。
这三条性质非常重要,是用来推导简化计算的必备知识。
public class BitwiseXOR {
public static void main(String[] args) {
int a = 5; // 二进制表示为 0101
int b = 3; // 二进制表示为 0011
// 按位异或操作
int result = a ^ b; // 结果为 0110,即十进制的 6
System.out.println("异或结果为: " + result); // 输出 6
// 使用异或交换两个变量的值
a = a ^ b; // a 现在为 6
b = a ^ b; // b 被赋值为原始的 a 值,即 5
a = a ^ b; // a 被赋值为原始的 b 值,即 3
System.out.println("交换后的 a 值为: " + a); // 输出 3
System.out.println("交换后的 b 值为: " + b); // 输出 5
}
}
如果把初始的a值看作m,初始的b值看作n:
b = a ^ b;
则这行a ^ b可以理解为m ^ n ^ n,而m ^ n ^ n = m ^( n ^ n),也就是得到m ^ 0 = m
a = a ^ b;
此时的b为m, a ^ b也就是 m ^ n ^ m,而m ^ n ^ m = n ^( m ^ m),也就是得到n ^ 0 = n
完成两个值的交换。
二、异或数列
给定一个数列,求数列中所有元素按位异或的值。
2.1 公差为1的数列
目标:计算数列从n到m的xorsum(n,m)值
我们先考虑从1到m的数列xorsum(1,m),每一个偶数i和i+1的异或i^(i+1)=1,考虑到这个特性,易得出
m%4 == 0
:xorsum(1,m)=mm%4 == 1
:xorsum(1,m)=1m%4 == 2
:xorsum(1,m)=m+1m%4 == 3
:xorsum(1,m)=0
xorsum(n,m) =xorsum(1,n-1)^xorsum(1,m)
在计算公差为1的数列的异或和时,结论是基于1到m的数列。在计算xorsum(n, m)时,可以通过xorsum(1, n-1) ^ xorsum(1, m)来得到结果,因为任何数与自己异或都是0,而n-1之前的数在n到m的范围内会出现两次,从而相互抵消
这样我们就得到了公差为1的数列对应xorsum(n,m)的值
2.2 公差为2^t的数列
目标:计算数列从n到n+2^t的数列元素异或值
-
t = 0时,为上文公差为1的情况
-
t = 1时,即公差为2,意味着数列每往后一个值都会加2,也就是相当于在二进制值中的倒数第二位加1,最后一位在不断加2的过程中保持不变。
以15,17,19为例:
十进制 | 二进制 |
---|---|
15 | 1111 |
17 | 10001 |
19 | 10011 |
所以不看最后一位,前面所有位最终值的确定就是求7 ^ 8 ^ 9,也就是xorsum(7,9),在前面已经解释了如何求解。
十进制 | 二进制 |
---|---|
7 | 111 |
8 | 1000 |
9 | 1001 |
最后一位的确定要根据数列第一个元素和数列元素个数的奇偶性确定,由于数列中最后一位都是相同的值,为0或1,所以不难得出:
数列第一个元素最后一位的值 | 元素个数 | 值 |
---|---|---|
0(偶数) | 偶数 | 0 |
0(偶数) | 奇数 | 0 |
1(奇数) | 偶数 | 0 |
1(奇数) | 奇数 | 1 |
下面是java实现的代码,供参考,其中start为数列首元素,n为数列元素个数。
class Solution {
public int xorsum(int n){
if (n < 0) return 0;
if (n % 4 == 1) return 1;
else if (n % 4 == 2) return n+1;
else if (n % 4 == 3) return 0;
else return n;
}
public int xorOperation(int n, int start) {
int a = start >> 1;
int b = a+n-1;
return ((xorsum(a-1)^xorsum(b))<<1) +(((start%2)+(n%2))>>1);
}
}
- t >1时,也就是二进制后边不变的位数更多,如t=3时,最后三位都需要分别判断最终值,判断方法同上文最后一位的确定。
总结
本文介绍了按位异或以及公差为2^t的数列中所有元素按位异或的值如何计算。