【算法】1442. 形成两个异或相等数组的三元组数目(多语言实现)

83 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情


1442. 形成两个异或相等数组的三元组数目:

给你一个整数数组 arr

现需要从数组中取三个下标 ijk ,其中 (0 <= i < j <= k < arr.length)

ab 定义如下:

  • 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
  • 1 <= arr[i] <= 108

分析

  • 面对这道算法题目,二当家的陷入了沉思。
  • 根据题意和x ^ x = 0,满足条件的i,j,k一定满足一个特点:arr[i] ^ ... ^ arr[k]=0,而这时候j(i,k]中的任何值都可以满足条件。
  • s[i] = arr[0] ^ ... ^ arr[i-1],当s[i]==s[k+1]相等时,展开可得arr[0] ^ ... ^ arr[i-1]==arr[0] ^ ... ^ arr[k],根据x ^ 0 = x可以推测出arr[i] ^ ... ^ arr[k]=0
  • 对于下标 k,若下标 i=i1,i2,⋯ ,im时均满足 Si=Sk+1,根据前面的推论可得答案数为(k−i1​)+(k−i2​)+⋯+(k−im​)=m⋅k−(i1​+i2​+⋯+im​)
  • 也就是说,当遍历下标 k 时,我们需要知道所有满足 Si=Sk+1​ 的
    1. 下标 i 的出现次数 m
    2. 下标 i 之和

题解

rust

impl Solution {
    pub fn count_triplets(arr: Vec<i32>) -> i32 {
        let mut ans = 0;
        // 前缀和
        let mut s = 0;
        let mut cnt: std::collections::HashMap<i32, i32> = std::collections::HashMap::new();
        let mut total: std::collections::HashMap<i32, i32> = std::collections::HashMap::new();
        arr.iter().enumerate().for_each(|(k, v)| {
            let t = s ^ v;
            if cnt.contains_key(&(t)) {
                ans += cnt[&(t)] * k as i32 - total[&(t)];
            }
            let counter = cnt.entry(s).or_insert(0);
            *counter += 1;
            let counter = total.entry(s).or_insert(0);
            *counter += k as i32;
            s = t;
        });
        return ans;
    }
}

go

func countTriplets(arr []int) (ans int) {
    // 前缀和
    s := 0
    cnt := map[int]int{}
    total := map[int]int{}
    for k, v := range arr {
        t := s ^ v
        if m, has := cnt[t]; has {
            ans += m*k - total[t]
        }
        cnt[s]++
        total[s] += k
        s = t
    }
    return
}

c++

class Solution {
public:
    int countTriplets(vector<int>& arr) {
        int ans = 0;
        // 前缀和
        int s = 0;
        int n = arr.size();
        unordered_map<int, int> cnt, total;
        for (int k = 0; k < n; ++k) {
            int t = s ^ arr[k];
            if (cnt.count(t)) {
                ans += cnt[t] * k - total[t];
            }
            ++cnt[s];
            total[s] += k;
            s = t;
        }
        return ans;
    }
};

java

class Solution {
    public int countTriplets(int[] arr) {
        int ans = 0;
        // 前缀和
        int s = 0;
        int n = arr.length;
        Map<Integer, Integer> cnt = new HashMap<Integer, Integer>();
        Map<Integer, Integer> total = new HashMap<Integer, Integer>();
        for (int k = 0; k < n; ++k) {
            int t = s ^ arr[k];
            if (cnt.containsKey(t)) {
                ans += cnt.get(t) * k - total.get(t);
            }
            cnt.put(s, cnt.getOrDefault(s, 0) + 1);
            total.put(s, total.getOrDefault(s, 0) + k);
            s = t;
        }
        return ans;
    }
}

python

class Solution:
    def countTriplets(self, arr: List[int]) -> int:
        ans = 0
        # 前缀和
        s = 0
        cnt, total = Counter(), Counter()

        for k, v in enumerate(arr):
            if (t := s ^ v) in cnt:
                ans += cnt[t] * k - total[t]
            cnt[s] += 1
            total[s] += k
            s = t

        return ans


原题传送门:https://leetcode.cn/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/


非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://juejin.cn/user/2771185768884824/posts 博客原创~