1442. 形成两个异或相等数组的三元组数目
思路:
类似的题做过了,一个优化算法就是(s0s1s2...si-1)(s0s1s2....si-1....sn)=(si...^sn).
因此我们就能计算出前缀异或的结果从而将暴力算法O(n4)优化成O(n3)
代码:
class Solution {
public:
int countTriplets(vector<int>& arr) {
unordered_map<int,int> xorpre;
int n = arr.size();
int pre=0;
int res=0;
for(int i=0;i<n;++i){
pre = pre ^ arr[i];
xorpre[i]=pre;
}
int a=0,b=0;
for(int i=0;i<n-1;++i){ //虽然有三个下标,但是因为 j<=k 所以不能 i 小于n-2,j不能小于n-1
for(int j=i+1;j<n;++j){
if(i==0){
a = xorpre[j-1];
}
else{
a = xorpre[j-1]^xorpre[i-1];
}
for(int k=j;k<n;++k){
b = xorpre[k]^xorpre[j-1];
if(a == b) res++;
}
}
}
return res;
}
};
我们注意到 a = b,那么计算我们还可以更为简洁一些。
由xorpre[k]xorpre[j-1]=xorpre[j-1]xorpre[i-1]
我们可得 xorpre[k] = xorpre[i-1]
那么三重for循环里的计算可以简化为如下:
class Solution {
public:
int countTriplets(vector<int>& arr) {
unordered_map<int,int> xorpre;
int n = arr.size();
int pre=0;
int res=0;
for(int i=0;i<n;++i){
pre = pre ^ arr[i];
xorpre[i]=pre;
}
for(int i=0;i<n-1;++i){
for(int j=i+1;j<n;++j){
for(int k=j;k<n;++k){
if(xorpre[k]==xorpre[i-1]) res++;
}
}
}
return res;
}
};
根据xorpre[k]=xorpre[i-1],那么我们可以知道,此时和j已经没有关系了,所以从k到i-1的这些数,我们都能满足a=b,所以每次res=k-i,因此我们可以优化成两重for循环,。
class Solution {
public:
int countTriplets(vector<int>& arr) {
unordered_map<int,int> xorpre;
int n = arr.size();
int pre=0;
int res=0;
for(int i=0;i<n;++i){
pre = pre ^ arr[i];
xorpre[i]=pre;
}
for(int i=0;i<n-1;++i){
for(int k=i+1;k<n;++k){
if(xorpre[k]==xorpre[i-1]) res += k-i;
}
}
return res;
}
};