题目大意:
给你一个整数数组 arr
,现需要从数组中取三个下标 i
、j
和 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
成立的三元组 (i, j , k)
的数目。
来源:力扣(LeetCode
)
链接:https://leetcode-cn.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor
解决思路:
首先有一点巧妙之处是,要想得到我们所要求的组合(i, j, k)
会满足一个性质。给出一个定义s(x) = arr[0] ^ arr[1] ^ ... ^ arr[x]
,所以要求的组合一定满足
s[i - 1] == s[k]
。该性质不难证明,因为a ^ b == 0
即s[i - 1] ^ (arr[i] ^ ... ^ arr[k])= s[i - 1] = s[k]
。
所以最后我们当 s[i - 1] == s[k]
时,有 j = i + 1 ~ k
共 k - i - 1
种方案。
接下来不用双重遍历,使用HashMap
一重遍历解决它。
时间复杂度:O(n) 空间复杂度:O(n)
class Solution {
public:
int countTriplets(vector<int> &arr) {
unordered_map<int, int> cnt, tot;
int pre = 0, ans = 0;
cnt[0] = 1;
tot[0] = 0;
for (int i = 0; i < arr.size(); i++) {
pre ^= arr[i];
if (cnt.count(pre)) {
ans += i * cnt[pre] - tot[pre];
}
cnt[pre]++;
tot[pre] += i + 1;
}
return ans;
}
};