[LeetCode解题报告] 1442. 形成两个异或相等数组的三元组数目

一、 题目

1. 题目描述

给你一个整数数组 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] <= 10^8
Related Topics
  • 位运算
  • 数组
  • 哈希表
  • 数学
  • 前缀和

  • 👍 206
  • 👎 0

2. 原题链接

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

二、 解题报告

1. 思路分析

抄袭官方题解。
题意实际是找两个相邻区间,使得这俩区间的异或和相同。

  1. 先求出前缀异或和S.
  2. 可证明:
  • 区间[i,j]的异或和为S[i,j]=S[i]^S[j+1]
  • 若S[i,j) ==S[j,k] 即 S[i]^S[j] == S[j]^S[k+1]
  • 上式可以转化为S[i]==S[k+1],此时j取(i,k]中的任意数都符合。
  1. 那么问题转化为:求满足条件的三元组i,j,k,有多少个
    那么我们枚举,i,j,当S[i]==S[k+1],j有多少个就计数上即可。这样是O(n2)
  2. 继续优化:
  • 对于每个k,若前边有m个i满足S[i]==S[k+1],这m个组合的和为:
    (k-i1)+(k-i2)+…(k-im-1)+(k-im)
    = m*k-(i1+i2+…im)
  • 即前边i的个数和i的和,用两个字典记。
    在这里插入图片描述

2. 复杂度分析

最坏时间复杂度O(n)

3. 代码实现

前缀异或和

class Solution:
    def countTriplets(self, arr: List[int]) -> int:
        n = len(arr)
        presum = list(accumulate(arr,initial=0,func=xor))
        def sum_interval(i,j):
            return presum[j+1]^presum[i]
        
        cnt,total = defaultdict(int),defaultdict(int)
        ans = 0
        for k in range(0,n):
            # presum[k+1] == presum[i] 则[i,k]中间j任意,都是满足需求的三元组
            s = presum[k+1]
            if s in cnt:
                ans += cnt[s]*k - total[s]
            cnt[presum[k]] += 1
            total[presum[k]] += k
        return ans
                

三、 本题小结

  1. 前缀异或和。

四、 参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值