前言
异或运算的定义与运算法则可参考《百度词条》。异或可以理解为不进位的加法运算,在解决奇数相关的问题时可以有很多妙用。
运算法则
- 归零律:a ^ a = 0
- 恒等律:a ^ 0 = a
- 交换律:a ^ b = b ^ a
- 结合律:a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c
- 自反律:a ^ b ^ a = b
- 可推导律:d = a ^ b ^ c => a = d ^ b ^ c
应用
1.交换顺序
在冒泡排序、选择排序等排序算法中经常会用到交换两个数字顺序的场景。场景主要是异或运算自反律的运用
public static void swap(int[] arr, int x, int y){
// 过滤无效数据
if (x < 0 ||x >= arr.length ||y < 0 ||y > arr.length){
return;
}
// 如果同一个索引会出现什么异常呢?
if (x == y){
return;
}
arr[x] = arr[x] ^ arr[y];
arr[y] = arr[x] ^ arr[y];
arr[x] = arr[x] ^ arr[y];
}
2.只出现一次的数字(leetcode-136)
这个题目是归零律的巧妙运用。运用场景比较受限,一个或者两个只出现一次的数字可以找到,但多个出现一次的数字就不能这么处理。下面是一个的情况,两个的该如何处理呢?
class Solution {
public int singleNumber(int[] nums) {
if(nums == null || nums.length == 0){
throw new RuntimeException("arr is empty");
}
int item = 0;
for(int i = 0; i < nums.length; i ++){
item ^= nums[i];
}
return item;
}
}
3.面试题
面试被问到:有N+1个同一型号磁盘存放数据,在保证磁盘的使用率的前提下,如何提升磁盘的容灾率?
这个题目就可以使用异或运算的可推导律,我们可以使用N个磁盘存放数据,多余的一块磁盘存放其他N个磁盘数据的异或结果,当其中某个磁盘数据出现异常时,可以通过其他N个磁盘的异或获得数据。