1442. Count Triplets That Can Form Two Arrays of Equal XOR
Problem Description
You are given an array of integers arr
. The task is to count how many triplets of indices (i, j, k)
exist such that a specific condition is met.
For each triplet, you need to select three indices where 0 <= i < j <= k < arr.length
. These indices divide the array into two segments:
- Segment
a
: XOR of all elements from indexi
toj-1
(i.e.,arr[i] ^ arr[i+1] ^ ... ^ arr[j-1]
) - Segment
b
: XOR of all elements from indexj
tok
(i.e.,arr[j] ^ arr[j+1] ^ ... ^ arr[k]
)
The goal is to find all triplets where a == b
.
The key insight is that if a == b
, then a ^ b = 0
. This means the XOR of all elements from index i
to k
equals 0. When this happens, we can place j
at any position between i+1
and k
(inclusive), and the condition a == b
will be satisfied.
The solution iterates through each possible starting position i
, then for each ending position k
, it calculates the XOR sum of elements from i
to k
. When this XOR sum equals 0, it means we've found k - i
valid triplets (since j
can be placed at any of the k - i
positions between i+1
and k
).
For example, if arr = [2, 3, 1, 6, 7]
and we find that XOR from index 0 to 2 equals 0 (i.e., 2 ^ 3 ^ 1 = 0
), then we have 2 valid triplets: (0, 1, 2)
and (0, 2, 2)
.
Intuition
The key observation is understanding what it means for a == b
in terms of XOR operations. Since a
represents the XOR of elements from index i
to j-1
, and b
represents the XOR from index j
to k
, when a == b
, something interesting happens mathematically.
If we XOR equal values together, we get 0. So if a == b
, then a ^ b = 0
. But what is a ^ b
? It's actually the XOR of all elements from index i
to k
. This is because:
a ^ b = (arr[i] ^ ... ^ arr[j-1]) ^ (arr[j] ^ ... ^ arr[k])
- This simplifies to
arr[i] ^ arr[i+1] ^ ... ^ arr[k]
So the problem reduces to finding all subarrays from index i
to k
where the XOR of all elements equals 0.
Once we find such a subarray where XOR equals 0, we need to count how many valid triplets it contains. The beauty here is that when the total XOR from i
to k
is 0, we can split this subarray at any position j
(where i < j <= k
), and the two parts will always have equal XOR values. This is because if the total XOR is 0, then a ^ b = 0
, which means a = b
.
There are exactly k - i
positions where we can place j
(from i+1
to k
inclusive). Each position gives us a valid triplet (i, j, k)
.
This insight allows us to simplify our approach: instead of checking all possible combinations of i
, j
, and k
separately, we only need to find pairs (i, k)
where the XOR from i
to k
equals 0, and then we automatically know there are k - i
valid triplets for that pair.
Learn more about Math and Prefix Sum patterns.
Solution Approach
The implementation uses a straightforward enumeration approach based on our insight that we need to find subarrays with XOR sum equal to 0.
The algorithm works as follows:
-
Initialize counters: We start with
ans = 0
to track the total count of valid triplets, and get the array lengthn
. -
Enumerate starting position
i
: We iterate through each possible starting indexi
from 0 ton-1
. For each starting position, we extract the elementx = arr[i]
and initialize our XOR sums
with this value. -
Enumerate ending position
k
: For each starting positioni
, we iterate through all possible ending positionsk
fromi+1
ton-1
. This ensures we have at least two elements in our subarray (required sincei < j <= k
). -
Calculate running XOR: As we extend
k
, we continuously update our XOR sum by computings ^= arr[k]
. This gives us the XOR of all elements from indexi
tok
. -
Check for valid subarrays: Whenever
s == 0
, we've found a subarray fromi
tok
where the total XOR is 0. This means we can placej
at any of thek - i
positions (fromi+1
tok
), and each placement gives us a valid triplet wherea == b
. -
Count the triplets: When we find
s == 0
, we addk - i
to our answer, representing all valid triplets for this(i, k)
pair.
The time complexity is O(n²)
since we have two nested loops iterating through the array. The space complexity is O(1)
as we only use a constant amount of extra space for variables.
This approach is efficient because instead of checking all O(n³)
possible triplets directly, we reduce the problem to checking O(n²)
pairs of (i, k)
and mathematically determining the count of valid j
values for each pair.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with arr = [2, 3, 1, 6, 7]
.
Step 1: Start with i = 0
- Initialize
x = arr[0] = 2
,s = 2
- Check k = 1:
s = 2 ^ 3 = 1
(not 0, skip) - Check k = 2:
s = 1 ^ 1 = 0
✓- Found XOR from i=0 to k=2 equals 0
- Can place j at positions 1 or 2
- Add
k - i = 2 - 0 = 2
triplets: (0,1,2) and (0,2,2)
- Check k = 3:
s = 0 ^ 6 = 6
(not 0, skip) - Check k = 4:
s = 6 ^ 7 = 1
(not 0, skip)
Step 2: Start with i = 1
- Initialize
x = arr[1] = 3
,s = 3
- Check k = 2:
s = 3 ^ 1 = 2
(not 0, skip) - Check k = 3:
s = 2 ^ 6 = 4
(not 0, skip) - Check k = 4:
s = 4 ^ 7 = 3
(not 0, skip)
Step 3: Start with i = 2
- Initialize
x = arr[2] = 1
,s = 1
- Check k = 3:
s = 1 ^ 6 = 7
(not 0, skip) - Check k = 4:
s = 7 ^ 7 = 0
✓- Found XOR from i=2 to k=4 equals 0
- Can place j at positions 3 or 4
- Add
k - i = 4 - 2 = 2
triplets: (2,3,4) and (2,4,4)
Step 4: Start with i = 3
- Initialize
x = arr[3] = 6
,s = 6
- Check k = 4:
s = 6 ^ 7 = 1
(not 0, skip)
Total count: 2 + 2 = 4 triplets
The valid triplets are:
- (0,1,2): a = 2, b = 3^1 = 2 ✓
- (0,2,2): a = 2^3 = 1, b = 1 ✓
- (2,3,4): a = 1, b = 6^7 = 1 ✓
- (2,4,4): a = 1^6 = 7, b = 7 ✓
Solution Implementation
1class Solution:
2 def countTriplets(self, arr: List[int]) -> int:
3 """
4 Count the number of triplets (i, j, k) where:
5 - 0 <= i < j <= k < n
6 - XOR of arr[i] to arr[j-1] equals XOR of arr[j] to arr[k]
7
8 Key insight: If XOR from i to k equals 0, then we can place j
9 anywhere between i+1 and k, giving us (k-i) valid triplets.
10
11 Args:
12 arr: List of integers
13
14 Returns:
15 Number of valid triplets
16 """
17 total_count = 0
18 array_length = len(arr)
19
20 # Iterate through each possible starting index i
21 for start_index in range(array_length):
22 # Initialize XOR accumulator with element at start_index
23 xor_sum = arr[start_index]
24
25 # Try all possible ending indices k (where k > i)
26 for end_index in range(start_index + 1, array_length):
27 # Accumulate XOR from start_index to end_index
28 xor_sum ^= arr[end_index]
29
30 # If XOR from start_index to end_index is 0,
31 # we can choose j at any position between them
32 if xor_sum == 0:
33 # Number of valid j positions is (end_index - start_index)
34 total_count += end_index - start_index
35
36 return total_count
37
1class Solution {
2 public int countTriplets(int[] arr) {
3 int tripletCount = 0;
4 int arrayLength = arr.length;
5
6 // Iterate through each possible starting position i
7 for (int i = 0; i < arrayLength; ++i) {
8 // Initialize XOR sum starting from index i
9 int xorSum = arr[i];
10
11 // Iterate through each possible ending position k (where k > i)
12 for (int k = i + 1; k < arrayLength; ++k) {
13 // Accumulate XOR sum from index i to k
14 xorSum ^= arr[k];
15
16 // If XOR sum from i to k equals 0, it means arr[i] ^ ... ^ arr[k] = 0
17 // This implies arr[i] ^ ... ^ arr[j-1] = arr[j] ^ ... ^ arr[k]
18 // There are (k - i) valid values for j, where j can be from i+1 to k
19 if (xorSum == 0) {
20 tripletCount += k - i;
21 }
22 }
23 }
24
25 return tripletCount;
26 }
27}
28
1class Solution {
2public:
3 int countTriplets(vector<int>& arr) {
4 int totalTriplets = 0;
5 int arraySize = arr.size();
6
7 // Iterate through all possible starting positions i
8 for (int startIndex = 0; startIndex < arraySize; ++startIndex) {
9 // Initialize XOR sum starting from arr[startIndex]
10 int xorSum = arr[startIndex];
11
12 // Try all possible ending positions k (where k > i)
13 for (int endIndex = startIndex + 1; endIndex < arraySize; ++endIndex) {
14 // Accumulate XOR sum from startIndex to endIndex
15 xorSum ^= arr[endIndex];
16
17 // If XOR of all elements from startIndex to endIndex is 0,
18 // then we can place j at any position between startIndex+1 and endIndex
19 // This gives us (endIndex - startIndex) valid triplets
20 if (xorSum == 0) {
21 totalTriplets += endIndex - startIndex;
22 }
23 }
24 }
25
26 return totalTriplets;
27 }
28};
29
1/**
2 * Counts the number of triplets (i, j, k) where i < j <= k
3 * such that arr[i] ^ arr[i+1] ^ ... ^ arr[j-1] == arr[j] ^ arr[j+1] ^ ... ^ arr[k]
4 *
5 * @param arr - The input array of numbers
6 * @returns The count of valid triplets
7 */
8function countTriplets(arr: number[]): number {
9 const arrayLength: number = arr.length;
10 let tripletCount: number = 0;
11
12 // Iterate through each possible starting index i
13 for (let startIndex: number = 0; startIndex < arrayLength; ++startIndex) {
14 // Initialize XOR sum starting from arr[startIndex]
15 let xorSum: number = arr[startIndex];
16
17 // Iterate through each possible ending index k (where k >= startIndex + 1)
18 for (let endIndex: number = startIndex + 1; endIndex < arrayLength; ++endIndex) {
19 // Update XOR sum to include arr[endIndex]
20 xorSum ^= arr[endIndex];
21
22 // If XOR of entire subarray [startIndex, endIndex] equals 0,
23 // then we can choose any j in range (startIndex, endIndex]
24 // giving us (endIndex - startIndex) valid triplets
25 if (xorSum === 0) {
26 tripletCount += endIndex - startIndex;
27 }
28 }
29 }
30
31 return tripletCount;
32}
33
Time and Space Complexity
The time complexity is O(n²)
, where n
is the length of the array arr
. This is because we have two nested loops: the outer loop iterates through each element in the array (running n
times), and for each element i
, the inner loop iterates from i+1
to n-1
. In the worst case, this gives us approximately n * (n-1) / 2
iterations, which simplifies to O(n²)
.
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space for variables ans
, n
, i
, x
, s
, and k
, regardless of the input array size. No additional data structures that scale with input size are created.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect XOR Initialization
A common mistake is initializing the XOR sum as 0 instead of arr[start_index]
. This leads to incorrect XOR calculations.
Incorrect:
for start_index in range(array_length):
xor_sum = 0 # Wrong! Missing arr[start_index]
for end_index in range(start_index + 1, array_length):
xor_sum ^= arr[end_index]
Correct:
for start_index in range(array_length):
xor_sum = arr[start_index] # Start with first element
for end_index in range(start_index + 1, array_length):
xor_sum ^= arr[end_index]
2. Misunderstanding Index Relationships
Many incorrectly assume j
must be strictly between i
and k
(i.e., i < j < k
), but the problem states i < j <= k
, meaning j
can equal k
.
Wrong interpretation leads to:
if xor_sum == 0: total_count += end_index - start_index - 1 # Wrong count!
Correct understanding:
if xor_sum == 0: total_count += end_index - start_index # j can be from i+1 to k inclusive
3. Attempting O(n³) Brute Force
Some try to directly enumerate all triplets, which is inefficient and unnecessary:
Inefficient approach:
for i in range(n):
for j in range(i + 1, n):
for k in range(j, n):
a = calculate_xor(i, j-1)
b = calculate_xor(j, k)
if a == b:
count += 1
Better approach: Use the XOR property that a == b
implies a ^ b == 0
, reducing to O(n²).
4. Off-by-One Errors in Loop Bounds
Forgetting that end_index
must start from start_index + 1
to ensure i < j
:
Wrong:
for end_index in range(start_index, array_length): # Allows i == j
Correct:
for end_index in range(start_index + 1, array_length): # Ensures i < j
5. Not Handling Edge Cases
Failing to consider arrays with length less than 2:
Solution:
if len(arr) < 2:
return 0 # No valid triplets possible
Depth first search is equivalent to which of the tree traversal order?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Prefix Sum The prefix sum is an incredibly powerful and straightforward technique Its primary goal is to allow for constant time range sum queries on an array What is Prefix Sum The prefix sum of an array at index i is the sum of all numbers from index 0 to i By
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!