题目名称:形成两个异或相等数组的三元组数目
给你一个整数数组 arr 。
现需要从数组中取三个下标 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) 的数目。
示例 1:
输入: arr = [2,3,1,6,7]
输出: 4
解释: 满足题意的三元组分别是 (0,1,2), (0,2,2), (2,3,4) 以及 (2,4,4)
示例 2:
输入: arr = [1,1,1,1,1]
输出: 10
示例 3:
输入: arr = [2,3]
输出: 0
示例 4:
输入: arr = [1,3,5,7,9]
输出: 3
示例 5:
输入: arr = [7,11,12,9,5,2,7,17,22]
输出: 8
提示:
1 <= arr.length <= 300
思路分析
遍历时每个元素,等于与前面所有元素异或操作的结果,并将结果存入HashMap<Integer, List>,key存异或的结果,List存索引,注意要提前插入一个0=[-1]。
- 两个连续的部分异或值相等,即整个区域异或值为0。
- 问题就转换成了,寻找异或值为0的区域,对于长度为n的区域,不同的划分个数为n-1。
- 计算前缀异或值,对于前缀异或值为0还有前缀异或值相等的区域,都要进行处理。
- 使用Map<Integer,List>存储异或值为key的索引列表
Code实现
public int countTriplets(int[] arr) {
int n = arr.length;
int[] preXor = new int[n];
Map < Integer, List < Integer >> map = new HashMap < > ();
preXor[0] = arr[0];
map.computeIfAbsent(preXor[0], o - > new ArrayList < Integer > ()).add(0);
int res = 0;
for (int i = 1; i < n; i++) {
preXor[i] = preXor[i - 1] ^ arr[i];
if (preXor[i] == 0) { //异或值为0,需要进行更新res
if (i >= 1) {
res += i;
}
}
if (map.containsKey(preXor[i])) { //将此时前缀异或值进行判断,并加入map
for (int index: map.get(preXor[i])) {
if (i - index >= 2) {
res += (i - index - 1);
}
}
map.get(preXor[i]).add(i);
} else {
map.computeIfAbsent(preXor[i], o - > new ArrayList < Integer > ()).add(i);
}
}
return res;
}
结果
算法复杂度分析
- 时间复杂度:
- 空间复杂度: