![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e799bc5d78fa168a83cc59d1c9e908b0.png)
思路: 异或的题目最近接连出了3天的每日一题。。。几乎每次都离不开运用异或的性质:a^b =c;a^c=b.同时**0与任何数异或都等于他本身。**我们还要注意到,两个相同的数字异或等于0.这意味着:两个相同的数字与任务数异或等于它本身 a^b=a,则b等于0。反过来a与某个数异或等于她本身,那个数一定等于0
这个题目详细的解析可以看官网题解. 思路比较巧妙。注意到就是构造数组的是时候有时候我们需要比正常的长度+1.一般这种做法有2个目的,一个是进行整体的平移,让第一位为空,这样数组可以表示为记录了当前index记录了在原来数组中index-1的数据。在dp问题中理解为空集。 当然这么做的初衷是因为dp问题需要前一个元素的参与,除非我提前设置dp[0]否则的确要多1个位置。这个题目哈希表的求解也比较巧妙。每次都是往哈希表里面记录元素,然后同时判断哈希表中是否出现过某元素用cnt.count(s[k + 1],如果出现过,证明出现s[i]=s[k+1]的情况~
方法1:二重循环
class Solution {
public:
int countTriplets(vector<int>& arr) {
//我们如果将下标K作为终点可以将数组区间分为3段
//i下标之前的一段,i到j-1的一段和j到k的一段。分别叫做abc
//要让b=c ,可得b^c必定等于0.所以 a^b^c=a^0=a
//根据上式因为a^b^c为从0-k的异或,所以a为从0到i的异或 所以只要满足这个条件,b可以是大于a小于等c的任意
//遍历下标i和k统计即可。
int n=arr.size();
vector<int> dp(n+1);
for(int i=0; i<n;i++)
dp[i+1]=dp[i]^arr[i]; //dp记录到这个下标之前的这段异或 能到---dp[n]
int ans=0;
for(int i=0;i<n;i++){
for(int k=i+1; k<n; k++){
if(dp[i]==dp[k+1])
ans+=k-i;
}
}
return ans;
}
};
方法3:一重循环
class Solution {
public:
int countTriplets(vector<int> &arr) {
int n = arr.size();
vector<int> s(n + 1);
for (int i = 0; i < n; ++i) {
s[i + 1] = s[i] ^ arr[i];
}
unordered_map<int, int> cnt, total;
int ans = 0;
for (int k = 0; k < n; ++k) {
if (cnt.count(s[k + 1])) {
ans += cnt[s[k + 1]] * k - total[s[k + 1]];
}
++cnt[s[k]];
total[s[k]] += k;
}
return ans;
}
};