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

题目描述

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

解法:(C++)

详细参考 java_Lee

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

对于累加 a [ 1 ] + a [ 2 ] + . . . a [ 9 ] = 0 a[1]+a[2]+...a[9]=0a[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]=0a[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 xxorxxor,如果 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]=0arr[i]arr[k]=0

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

至于在取 j jj 的所有情况的时候,我们采用了前 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-1i1, 而 j jj 总共是 k − i k-iki 种情况,所以 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;
    }
};

版权声明:本文为qq_38204302原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。