Before attempting this problem, you should be comfortable with:
Bitwise XOR - Understanding XOR properties like a XOR a = 0 and a XOR 0 = a
Prefix Sums/XOR - Using cumulative operations to compute subarray results efficiently
Hash Maps - Tracking counts and index sums for O(1) lookups in the optimal solution
1. Brute Force
Intuition
We need to find triplets (i, j, k) where a = arr[i] XOR arr[i+1] XOR ... XOR arr[j-1] equals b = arr[j] XOR arr[j+1] XOR ... XOR arr[k]. The most direct approach is to try all valid combinations of i, j, and k, compute both XOR values for each triplet, and count when they match.
Algorithm
Initialize a result counter res to 0.
Iterate through all possible values of i from 0 to N-2.
For each i, iterate through all possible values of j from i+1 to N-1.
For each j, iterate through all possible values of k from j to N-1.
classSolution:defcountTriplets(self, arr: List[int])->int:
N =len(arr)
res =0for i inrange(N -1):for j inrange(i +1, N):for k inrange(j, N):
a = b =0for idx inrange(i, j):
a ^= arr[idx]for idx inrange(j, k +1):
b ^= arr[idx]if a == b:
res +=1return res
publicclassSolution{publicintcountTriplets(int[] arr){intN= arr.length;int res =0;for(int i =0; i <N-1; i++){for(int j = i +1; j <N; j++){for(int k = j; k <N; k++){int a =0, b =0;for(int idx = i; idx < j; idx++){
a ^= arr[idx];}for(int idx = j; idx <= k; idx++){
b ^= arr[idx];}if(a == b){
res++;}}}}return res;}}
classSolution{public:intcountTriplets(vector<int>& arr){int N = arr.size();int res =0;for(int i =0; i < N -1;++i){for(int j = i +1; j < N;++j){for(int k = j; k < N;++k){int a =0, b =0;for(int idx = i; idx < j;++idx){
a ^= arr[idx];}for(int idx = j; idx <= k;++idx){
b ^= arr[idx];}if(a == b){
res++;}}}}return res;}};
classSolution{/**
* @param {number[]} arr
* @return {number}
*/countTriplets(arr){constN= arr.length;let res =0;for(let i =0; i <N-1; i++){for(let j = i +1; j <N; j++){for(let k = j; k <N; k++){let a =0,
b =0;for(let idx = i; idx < j; idx++){
a ^= arr[idx];}for(let idx = j; idx <= k; idx++){
b ^= arr[idx];}if(a === b){
res++;}}}}return res;}}
publicclassSolution{publicintCountTriplets(int[] arr){int N = arr.Length;int res =0;for(int i =0; i < N -1; i++){for(int j = i +1; j < N; j++){for(int k = j; k < N; k++){int a =0, b =0;for(int idx = i; idx < j; idx++){
a ^= arr[idx];}for(int idx = j; idx <= k; idx++){
b ^= arr[idx];}if(a == b){
res++;}}}}return res;}}
funccountTriplets(arr []int)int{
N :=len(arr)
res :=0for i :=0; i < N-1; i++{for j := i +1; j < N; j++{for k := j; k < N; k++{
a, b :=0,0for idx := i; idx < j; idx++{
a ^= arr[idx]}for idx := j; idx <= k; idx++{
b ^= arr[idx]}if a == b {
res++}}}}return res
}
class Solution {funcountTriplets(arr: IntArray): Int {val N = arr.size
var res =0for(i in0 until N -1){for(j in i +1 until N){for(k in j until N){var a =0var b =0for(idx in i until j){
a = a xor arr[idx]}for(idx in j..k){
b = b xor arr[idx]}if(a == b){
res++}}}}return res
}}
classSolution{funccountTriplets(_ arr:[Int])->Int{letN= arr.count
var res =0for i in0..<(N-1){for j in(i +1)..<N{for k in j..<N{var a =0, b =0for idx in i..<j {
a ^= arr[idx]}for idx in j...k {
b ^= arr[idx]}if a == b {
res +=1}}}}return res
}}
Time & Space Complexity
Time complexity: O(n4)
Space complexity: O(1) extra space.
2. Brute Force (Optimized)
Intuition
Instead of recomputing the XOR values from scratch for each triplet, we can build them incrementally. As we move j forward, we can extend a by XORing the next element. Similarly, as we move k forward, we can extend b by XORing the next element. This eliminates the innermost loops for computing XOR values.
Algorithm
Initialize a result counter res to 0.
Iterate through all possible values of i from 0 to N-2.
classSolution:defcountTriplets(self, arr: List[int])->int:
N =len(arr)
res =0for i inrange(N -1):
a =0for j inrange(i +1, N):
a ^= arr[j -1]
b =0for k inrange(j, N):
b ^= arr[k]if a == b:
res +=1return res
publicclassSolution{publicintcountTriplets(int[] arr){intN= arr.length;int res =0;for(int i =0; i <N-1; i++){int a =0;for(int j = i +1; j <N; j++){
a ^= arr[j -1];int b =0;for(int k = j; k <N; k++){
b ^= arr[k];if(a == b){
res++;}}}}return res;}}
classSolution{public:intcountTriplets(vector<int>& arr){int N = arr.size();int res =0;for(int i =0; i < N -1;++i){int a =0;for(int j = i +1; j < N;++j){
a ^= arr[j -1];int b =0;for(int k = j; k < N;++k){
b ^= arr[k];if(a == b){
res++;}}}}return res;}};
classSolution{/**
* @param {number[]} arr
* @return {number}
*/countTriplets(arr){constN= arr.length;let res =0;for(let i =0; i <N-1; i++){let a =0;for(let j = i +1; j <N; j++){
a ^= arr[j -1];let b =0;for(let k = j; k <N; k++){
b ^= arr[k];if(a === b){
res++;}}}}return res;}}
publicclassSolution{publicintCountTriplets(int[] arr){int N = arr.Length;int res =0;for(int i =0; i < N -1; i++){int a =0;for(int j = i +1; j < N; j++){
a ^= arr[j -1];int b =0;for(int k = j; k < N; k++){
b ^= arr[k];if(a == b){
res++;}}}}return res;}}
funccountTriplets(arr []int)int{
N :=len(arr)
res :=0for i :=0; i < N-1; i++{
a :=0for j := i +1; j < N; j++{
a ^= arr[j-1]
b :=0for k := j; k < N; k++{
b ^= arr[k]if a == b {
res++}}}}return res
}
class Solution {funcountTriplets(arr: IntArray): Int {val N = arr.size
var res =0for(i in0 until N -1){var a =0for(j in i +1 until N){
a = a xor arr[j -1]var b =0for(k in j until N){
b = b xor arr[k]if(a == b){
res++}}}}return res
}}
classSolution{funccountTriplets(_ arr:[Int])->Int{letN= arr.count
var res =0for i in0..<(N-1){var a =0for j in(i +1)..<N{
a ^= arr[j -1]var b =0for k in j..<N{
b ^= arr[k]if a == b {
res +=1}}}}return res
}}
Time & Space Complexity
Time complexity: O(n3)
Space complexity: O(1) extra space.
3. Math + Bitwise XOR
Intuition
The key insight is that if a == b, then a XOR b == 0, which means arr[i] XOR arr[i+1] XOR ... XOR arr[k] == 0. So we need to find subarrays where the XOR of all elements is 0. For any such subarray from index i to k, we can place j at any position from i+1 to k, giving us k - i valid triplets. This reduces the problem to finding pairs (i, k) where the subarray XOR is 0.
Algorithm
Initialize a result counter res to 0.
Iterate through all possible starting indices i from 0 to N-2.
Initialize cur_xor to arr[i].
For each ending index k from i+1 to N-1:
Update cur_xor by XORing it with arr[k].
If cur_xor == 0, add k - i to res (representing all valid positions for j).
classSolution:defcountTriplets(self, arr: List[int])->int:
N =len(arr)
res =0for i inrange(N -1):
cur_xor = arr[i]for k inrange(i +1, N):
cur_xor ^= arr[k]if cur_xor ==0:
res += k - i
return res
publicclassSolution{publicintcountTriplets(int[] arr){intN= arr.length;int res =0;for(int i =0; i <N-1; i++){int curXor = arr[i];for(int k = i +1; k <N; k++){
curXor ^= arr[k];if(curXor ==0){
res += k - i;}}}return res;}}
classSolution{public:intcountTriplets(vector<int>& arr){int N = arr.size();int res =0;for(int i =0; i < N -1;++i){int curXor = arr[i];for(int k = i +1; k < N;++k){
curXor ^= arr[k];if(curXor ==0){
res += k - i;}}}return res;}};
classSolution{/**
* @param {number[]} arr
* @return {number}
*/countTriplets(arr){constN= arr.length;let res =0;for(let i =0; i <N-1; i++){let curXor = arr[i];for(let k = i +1; k <N; k++){
curXor ^= arr[k];if(curXor ===0){
res += k - i;}}}return res;}}
publicclassSolution{publicintCountTriplets(int[] arr){int N = arr.Length;int res =0;for(int i =0; i < N -1; i++){int curXor = arr[i];for(int k = i +1; k < N; k++){
curXor ^= arr[k];if(curXor ==0){
res += k - i;}}}return res;}}
funccountTriplets(arr []int)int{
N :=len(arr)
res :=0for i :=0; i < N-1; i++{
curXor := arr[i]for k := i +1; k < N; k++{
curXor ^= arr[k]if curXor ==0{
res += k - i
}}}return res
}
class Solution {funcountTriplets(arr: IntArray): Int {val N = arr.size
var res =0for(i in0 until N -1){var curXor = arr[i]for(k in i +1 until N){
curXor = curXor xor arr[k]if(curXor ==0){
res += k - i
}}}return res
}}
classSolution{funccountTriplets(_ arr:[Int])->Int{letN= arr.count
var res =0for i in0..<(N-1){var curXor = arr[i]for k in(i +1)..<N{
curXor ^= arr[k]if curXor ==0{
res += k - i
}}}return res
}}
Time & Space Complexity
Time complexity: O(n2)
Space complexity: O(1) extra space.
4. Math + Bitwise XOR (Optimal)
Intuition
We can use prefix XOR to find subarrays with XOR equal to 0 in linear time. If prefix[i] == prefix[k+1], then the XOR from index i to k is 0. For each prefix value, we track how many times we have seen it and the sum of indices where it occurred. When we see the same prefix again at index k, the contribution to the result is k * count - sum_of_indices, where count is how many times this prefix appeared before, and the formula accounts for all k - i values.
Algorithm
Initialize res and prefix to 0.
Create two hash maps: count to store frequency of each prefix value, and index_sum to store sum of indices for each prefix value.
Initialize count[0] = 1 to handle subarrays starting from index 0.
For each index i from 0 to N-1:
Update prefix by XORing it with arr[i].
If this prefix value has been seen before, add i * count[prefix] - index_sum[prefix] to res.
classSolution:defcountTriplets(self, arr: List[int])->int:
N =len(arr)
res = prefix =0
count = defaultdict(int)# number of prefixes
index_sum = defaultdict(int)# sum of indices with that prefix
count[0]=1for i inrange(N):
prefix ^= arr[i]if prefix in count:
res += i * count[prefix]- index_sum[prefix]
count[prefix]+=1
index_sum[prefix]+= i +1return res
publicclassSolution{publicintcountTriplets(int[] arr){intN= arr.length, res =0, prefix =0;Map<Integer,Integer> count =newHashMap<>();// number of prefixesMap<Integer,Integer> indexSum =newHashMap<>();// sum of indices with that prefix
count.put(0,1);for(int i =0; i <N; i++){
prefix ^= arr[i];if(count.containsKey(prefix)){
res += i * count.get(prefix)- indexSum.getOrDefault(prefix,0);}
count.put(prefix, count.getOrDefault(prefix,0)+1);
indexSum.put(prefix, indexSum.getOrDefault(prefix,0)+ i +1);}return res;}}
classSolution{public:intcountTriplets(vector<int>& arr){int N = arr.size(), res =0, prefix =0;
unordered_map<int,int> count;// number of prefixes
unordered_map<int,int> indexSum;// sum of indices with that prefix
count[0]=1;for(int i =0; i < N; i++){
prefix ^= arr[i];if(count.count(prefix)){
res += i * count[prefix]- indexSum[prefix];}
count[prefix]++;
indexSum[prefix]+= i +1;}return res;}};
classSolution{/**
* @param {number[]} arr
* @return {number}
*/countTriplets(arr){constN= arr.length;let res =0,
prefix =0;const count =newMap();// number of prefixesconst indexSum =newMap();// sum of indices with that prefix
count.set(0,1);for(let i =0; i <N; i++){
prefix ^= arr[i];if(count.has(prefix)){
res += i * count.get(prefix)-(indexSum.get(prefix)||0);}
count.set(prefix,(count.get(prefix)||0)+1);
indexSum.set(prefix,(indexSum.get(prefix)||0)+ i +1);}return res;}}
publicclassSolution{publicintCountTriplets(int[] arr){int N = arr.Length, res =0, prefix =0;Dictionary<int,int> count =newDictionary<int,int>();Dictionary<int,int> indexSum =newDictionary<int,int>();
count[0]=1;for(int i =0; i < N; i++){
prefix ^= arr[i];if(count.ContainsKey(prefix)){
res += i * count[prefix]-(indexSum.ContainsKey(prefix)? indexSum[prefix]:0);}
count[prefix]= count.GetValueOrDefault(prefix,0)+1;
indexSum[prefix]= indexSum.GetValueOrDefault(prefix,0)+ i +1;}return res;}}
funccountTriplets(arr []int)int{
N :=len(arr)
res, prefix :=0,0
count :=make(map[int]int)
indexSum :=make(map[int]int)
count[0]=1for i :=0; i < N; i++{
prefix ^= arr[i]if c, ok := count[prefix]; ok {
res += i*c - indexSum[prefix]}
count[prefix]++
indexSum[prefix]+= i +1}return res
}
class Solution {funcountTriplets(arr: IntArray): Int {val N = arr.size
var res =0var prefix =0val count =mutableMapOf(0to1)val indexSum = mutableMapOf<Int, Int>()for(i in0 until N){
prefix = prefix xor arr[i]if(prefix in count){
res += i * count[prefix]!!-(indexSum[prefix]?:0)}
count[prefix]=(count[prefix]?:0)+1
indexSum[prefix]=(indexSum[prefix]?:0)+ i +1}return res
}}
classSolution{funccountTriplets(_ arr:[Int])->Int{letN= arr.count
var res =0,prefix=0var count =[0:1]var indexSum =[Int:Int]()for i in0..<N{prefix^= arr[i]iflet c = count[prefix]{
res += i * c -(indexSum[prefix]??0)}
count[prefix,default:0]+=1
indexSum[prefix,default:0]+= i +1}return res
}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
Common Pitfalls
Misunderstanding the Triplet Count Formula
When the XOR from index i to k equals zero, beginners often count it as just 1 triplet. However, j can be placed at any position from i+1 to k, yielding k - i valid triplets for each such pair.
# Incorrect - counts only one triplet per zero-XOR subarrayif cur_xor ==0:
res +=1# Correct - counts all valid j positionsif cur_xor ==0:
res += k - i
Off-by-One Errors in Index Sum Tracking
In the optimal solution, the index sum needs to track i + 1 (not i) because we want the sum of starting positions for subarrays, and the formula i * count - index_sum requires this offset. Using just i leads to incorrect results.
# Incorrect - missing the +1 offset
index_sum[prefix]+= i
# Correct - accounts for 1-based position in contribution formula
index_sum[prefix]+= i +1
Forgetting to Initialize count[0] = 1
The prefix XOR of 0 needs to be pre-initialized to handle subarrays starting from index 0. Without this initialization, valid triplets where the XOR from index 0 to some k equals zero will be missed.
# Incorrect - misses subarrays starting from index 0
count = defaultdict(int)# Correct - handles prefix XOR that equals a previously seen value at index 0
count = defaultdict(int)
count[0]=1