LeetCode 1442. 形成两个异或相等数组的三元组数目(周赛)

题目描述

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

解法:(C++)

详细参考 java_Lee

其实这道题有个超好理解的地方,如果 a = = b a==b a==b,那么 a ⊕ b = 0 a\oplus b=0 ab=0,这样我们就超好找到能满足条件的子区间了。

对于累加 a [ 1 ] + a [ 2 ] + . . . a [ 9 ] = 0 a[1]+a[2]+...a[9]=0 a[1]+a[2]+...a[9]=0 等价于 s u m ( 9 ) − s u m ( 0 ) sum(9)-sum(0) sum(9)sum(0)(存在 a [ 0 ] a[0] a[0]),即 a [ i ] + a [ i + 1 ] + . . . + a [ k ] = 0 a[i]+a[i+1]+...+a[k]=0 a[i]+a[i+1]+...+a[k]=0,只需要 s u m ( k ) = = − s u m ( i − 1 ) sum(k)==-sum(i-1) sum(k)==sum(i1)

记累积异或的结果为 x x o r xxor xxor,如果 x x o r ( i − 1 ) = x x o r ( k ) xxor(i-1)=xxor(k) xxor(i1)=xxor(k),那么 a r r [ i ] ⊕ ⋯ ⊕ a r r [ k ] = 0 arr[i]\oplus \cdots \oplus arr[k]=0 arr[i]arr[k]=0

于是,就可以用一个哈希表来记录累积异或值相同时的下标了,然后对于三元组 ( i , j , k ) (i,j,k) (i,j,k) j j j 可以取遍 i + 1 , ⋯   , k i+1,\cdots,k i+1,,k k − i k-i ki种情况

至于在取 j j j 的所有情况的时候,我们采用了前 n 项和的思想取缔了一层嵌套循环

for(int i=0;i<indx.size()-1;i++)
{
	int start = indx[i]+1;
    for(int j=i+1;j<=indx.size()-1;j++)
    	ans += indx[j]-start;
}

对于三元组 ( i , j , k ) (i,j,k) (i,j,k),记录的起始下标是 i − 1 i-1 i1, 而 j j j 总共是 k − i k-i ki 种情况,所以 int start = indx[i]+1;

改进后,时间复杂度可以从 O ( n 2 ) O(n^2) O(n2) 降到 O ( n ) O(n) O(n)

vector<int> ssum(indx);
for(int i=1;i<ssum.size();i++)
	ssum[i] += ssum[i-1];
int n = ssum.size()-1;
for(int i=0;i<n;i++)
    ans += ssum[n]-ssum[i]-(n-i)*(indx[i]+1);

最后是完整的代码

class Solution {
public:
    int countTriplets(vector<int>& arr) {
        unordered_map<int, vector<int>> table;
        table[0] = {-1};
        int xxor = 0;
        for(int i=0;i<arr.size();i++)
            table[(xxor^=arr[i])].push_back(i);
        int ans = 0;
        for(auto item: table)
        {
            vector<int>& indx = item.second;
            vector<int> ssum(indx);
            for(int i=1;i<ssum.size();i++)
                ssum[i] += ssum[i-1];
            int n = ssum.size()-1;
            for(int i=0;i<n;i++)
                ans += ssum[n]-ssum[i]-(n-i)*(indx[i]+1);
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值