LC1442-形成两个异或相等数组的三元组数目

98 阅读1分钟

题目名称:形成两个异或相等数组的三元组数目

给你一个整数数组 arr 。

现需要从数组中取三个下标 ij 和 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 成立的三元组 (ij , 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
  • 1<=arr[i]<=1081 <= arr[i] <= 10^8

思路分析

遍历时每个元素,等于与前面所有元素异或操作的结果,并将结果存入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;
}

结果

Snipaste_2023-05-10_23-12-15.png

算法复杂度分析

  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(n)O(n)