1.异或的概念(对于新手)
异或是一种逻辑运算符,对两个数异或的结果实际是看其在二进制下比特位是否相同:
异或运算符 ^ (⊕)
核心:二进制下对应位值相同为0,不同为1
/*
假设我们要对9和7进行异或,其中9的二进制为1001,7为0111
7 -- 0 1 1 1
⊕
9 -- 1 0 0 1
-----------
14-- 1 1 1 0
因此7^9 = 14
*/
/*
异或的一些基本运算规则:
a ^ a = 0,
0 ^ a = a,
a ^ b = b ^ a,
a ^ (b ^ c) = (a ^ b) ^ c
*/
2.前缀异或数组
在做异或题目时,经常需要计算区间内的异或值,为了避免使用暴力方法运算,就要用到前缀异或数组的方法:
假设我们有数组arr{1,2,3,4,7,9}
前0项的异或值为:0 = 0
前1项的异或值为:0 ^ 1 = 1
前2项的异或值为:1 ^ 2 = 3
前3项的异或值为:1 ^ 2 ^ 3 = 0
前4项的异或值为:1 ^ 2 ^ 3 ^ 4 = 4
前5项的异或值为:1 ^ 2 ^ 3 ^ 4 ^ 7 = 3
前6项的异或值为:1 ^ 2 ^ 3 ^ 4 ^ 7 ^ 9 = 10
因此他们的前缀异或数组为pre{0,1,3,0,4,3,10}
假设我们要计算arr数组第3到第六项的异或值,此时我们不需要暴力的去计算:
“3 ^ 4 ^ 7 ^ 9”
因为我们知道(3 ^ 4 ^ 7 ^ 9) = (1 ^ 2) ^ (1 ^ 2 ^ 3 ^ 4 ^ 7 ^ 9)
很明显:1 ^ 2是前2项的值;1 ^ 2 ^ 3 ^ 4 ^ 7 ^ 9是前6项的值
因此第3到第6项的值为:3 ^ 10 = 9
当求第m到第n项的异或值:pre[m-1] ^ pre[n]
举个栗子(LeetCode 1442):
题目:现需要从数组中取三个下标 i、j 和 k ,其中 (0 <= i < j <= k < arr.length) 。
a 和 b 定义如下:
a = arr[i] ^ arr[i + 1] ^ … ^ arr[j - 1]
b = arr[j] ^ arr[j + 1] ^ … ^ arr[k]
请返回能够令 a == b 成立的三元组 (i, j , k) 的数目。
class Solution {
public int countTriplets(</