Facebook Pixel

3215. Count Triplets with Even XOR Set Bits II 🔒

MediumBit ManipulationArray
Leetcode Link

Problem Description

You are given three integer arrays a, b, and c. Your task is to count how many triplets (a[i], b[j], c[k]) exist such that when you perform bitwise XOR operation on all three elements (a[i] XOR b[j] XOR c[k]), the result has an even number of set bits (1s in binary representation).

For example, if the XOR result is 10110 in binary, it has 3 set bits (three 1s), which is odd, so this triplet wouldn't be counted. But if the XOR result is 1001 in binary, it has 2 set bits (two 1s), which is even, so this triplet would be counted.

The key insight is that when XORing numbers, the parity (odd/even property) of set bits in the final result depends on the sum of parities of set bits in the individual numbers. If the sum of the number of set bits across the three numbers has a specific parity pattern, the XOR result will have an even number of set bits.

The solution leverages this property by:

  1. Counting the parity of set bits for each number in arrays a, b, and c
  2. Using the fact that for XOR of three numbers to have even set bits, the sum of their individual set bit parities must follow a specific pattern
  3. Multiplying the counts of matching parity combinations to get the total number of valid triplets
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key observation is that counting set bits in XOR results directly for all possible triplets would be inefficient. Instead, we need to find a pattern.

When we XOR three numbers, the parity (odd/even) of set bits in the result follows a mathematical rule. Let's think about how XOR works: for each bit position, XOR counts how many 1s appear across all numbers - if it's odd, the result bit is 1; if even, it's 0.

For three numbers x, y, and z, if they have p, q, and r set bits respectively, the parity of set bits in x XOR y XOR z depends on (p + q + r) mod 2. More specifically, when we XOR three numbers bit by bit, the final count of 1s has a predictable parity based on the individual parities.

Here's the crucial insight: instead of computing the actual XOR and counting bits for each triplet, we can just track whether each number has an odd or even number of set bits (parity = 0 for even, 1 for odd).

For the XOR result to have an even number of set bits, we need the sum of parities (i + j + k) to satisfy a specific condition. Through XOR properties, we can determine that when (i + j + k) & 1 ^ 1 is true (which means the sum is even), the XOR result will have an even number of set bits.

This transforms our problem from O(n³) brute force checking into a counting problem: we count how many numbers in each array have even/odd parity of set bits, then multiply the counts for valid parity combinations. This gives us all valid triplets without actually computing each XOR operation.

Solution Approach

The solution uses bit manipulation and counting to efficiently solve the problem.

First, we create three counters cnt1, cnt2, and cnt3 to track the parity of set bits for each number in arrays a, b, and c respectively. For each number x in an array, we compute x.bit_count() & 1:

  • x.bit_count() returns the number of 1s in the binary representation of x
  • & 1 gives us the parity (0 if even number of 1s, 1 if odd number of 1s)

The Counter stores how many numbers in each array have even parity (0) and how many have odd parity (1).

Next, we enumerate all possible parity combinations using three nested loops, where i, j, and k each range from 0 to 1:

  • i represents the parity for numbers from array a
  • j represents the parity for numbers from array b
  • k represents the parity for numbers from array c

For each combination (i, j, k), we check if (i + j + k) & 1 ^ 1 is true:

  • (i + j + k) gives the sum of parities
  • & 1 gets the least significant bit (parity of the sum)
  • ^ 1 flips the bit (equivalent to checking if the sum is even)

When this condition is true, it means the XOR of any triplet with these parities will have an even number of set bits. We then multiply cnt1[i] * cnt2[j] * cnt3[k] to get the number of valid triplets for this parity combination and add it to our answer.

The multiplication works because each element with parity i from array a can be paired with each element with parity j from array b and each element with parity k from array c, giving us all possible triplets with the desired property.

Finally, we return the total count accumulated across all valid parity combinations.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example to illustrate the solution approach.

Given:

  • a = [3, 5]
  • b = [2, 6]
  • c = [1, 4]

Step 1: Calculate parity of set bits for each number

For array a:

  • 3 in binary is 11 → 2 set bits → parity = 0 (even)
  • 5 in binary is 101 → 2 set bits → parity = 0 (even)
  • cnt1 = {0: 2, 1: 0} (both numbers have even parity)

For array b:

  • 2 in binary is 10 → 1 set bit → parity = 1 (odd)
  • 6 in binary is 110 → 2 set bits → parity = 0 (even)
  • cnt2 = {0: 1, 1: 1} (one even, one odd)

For array c:

  • 1 in binary is 1 → 1 set bit → parity = 1 (odd)
  • 4 in binary is 100 → 1 set bit → parity = 1 (odd)
  • cnt3 = {0: 0, 1: 2} (both numbers have odd parity)

Step 2: Check all parity combinations

We iterate through all combinations of (i, j, k) where each can be 0 or 1:

  • (0, 0, 0): Sum = 0, (0 & 1) ^ 1 = 1 ✓ Valid

    • Count = cnt1[0] * cnt2[0] * cnt3[0] = 2 * 1 * 0 = 0
  • (0, 0, 1): Sum = 1, (1 & 1) ^ 1 = 0 ✗ Invalid

  • (0, 1, 0): Sum = 1, (1 & 1) ^ 1 = 0 ✗ Invalid

  • (0, 1, 1): Sum = 2, (2 & 1) ^ 1 = 1 ✓ Valid

    • Count = cnt1[0] * cnt2[1] * cnt3[1] = 2 * 1 * 2 = 4
  • (1, 0, 0): Sum = 1, (1 & 1) ^ 1 = 0 ✗ Invalid

  • (1, 0, 1): Sum = 2, (2 & 1) ^ 1 = 1 ✓ Valid

    • Count = cnt1[1] * cnt2[0] * cnt3[1] = 0 * 1 * 2 = 0
  • (1, 1, 0): Sum = 2, (2 & 1) ^ 1 = 1 ✓ Valid

    • Count = cnt1[1] * cnt2[1] * cnt3[0] = 0 * 1 * 0 = 0
  • (1, 1, 1): Sum = 3, (3 & 1) ^ 1 = 0 ✗ Invalid

Step 3: Sum up valid combinations

Total = 0 + 4 + 0 + 0 = 4

Verification: The 4 valid triplets are:

  1. (3, 2, 1): 3 XOR 2 XOR 1 = 0 → 0 set bits (even) ✓
  2. (3, 2, 4): 3 XOR 2 XOR 4 = 5 → 2 set bits (even) ✓
  3. (5, 2, 1): 5 XOR 2 XOR 1 = 6 → 2 set bits (even) ✓
  4. (5, 2, 4): 5 XOR 2 XOR 4 = 3 → 2 set bits (even) ✓

All other triplets like (3, 6, 1) would give 3 XOR 6 XOR 1 = 4 → 1 set bit (odd), which wouldn't be counted.

Solution Implementation

1from typing import List
2from collections import Counter
3
4class Solution:
5    def tripletCount(self, a: List[int], b: List[int], c: List[int]) -> int:
6        # Count the parity (even=0, odd=1) of bit counts for each array
7        # bit_count() returns the number of 1s in binary representation
8        # & 1 gives us the parity (0 for even, 1 for odd)
9        parity_count_a = Counter(x.bit_count() & 1 for x in a)
10        parity_count_b = Counter(x.bit_count() & 1 for x in b)
11        parity_count_c = Counter(x.bit_count() & 1 for x in c)
12      
13        result = 0
14      
15        # Iterate through all possible parity combinations
16        for parity_a in range(2):  # 0 (even) or 1 (odd)
17            for parity_b in range(2):  # 0 (even) or 1 (odd)
18                for parity_c in range(2):  # 0 (even) or 1 (odd)
19                    # Check if the sum of parities is even
20                    # (i + j + k) & 1 gives 0 if sum is even, 1 if odd
21                    # ^ 1 flips the bit, so we count when sum is even
22                    if ((parity_a + parity_b + parity_c) & 1) == 0:
23                        # Multiply the counts of elements with these parities
24                        result += (parity_count_a[parity_a] * 
25                                 parity_count_b[parity_b] * 
26                                 parity_count_c[parity_c])
27      
28        return result
29
1class Solution {
2    /**
3     * Counts the number of valid triplets (i, j, k) where elements from arrays a, b, and c
4     * form a triplet with an even sum of their bit counts.
5     * 
6     * @param a First array
7     * @param b Second array  
8     * @param c Third array
9     * @return Number of valid triplets
10     */
11    public long tripletCount(int[] a, int[] b, int[] c) {
12        // Count elements by bit count parity (even=0, odd=1) for each array
13        int[] parityCountA = new int[2];  // [evenBitCount, oddBitCount]
14        int[] parityCountB = new int[2];
15        int[] parityCountC = new int[2];
16      
17        // Count elements in array 'a' by bit count parity
18        for (int element : a) {
19            int bitCount = Integer.bitCount(element);
20            int parity = bitCount & 1;  // 0 if even bit count, 1 if odd
21            parityCountA[parity]++;
22        }
23      
24        // Count elements in array 'b' by bit count parity
25        for (int element : b) {
26            int bitCount = Integer.bitCount(element);
27            int parity = bitCount & 1;
28            parityCountB[parity]++;
29        }
30      
31        // Count elements in array 'c' by bit count parity
32        for (int element : c) {
33            int bitCount = Integer.bitCount(element);
34            int parity = bitCount & 1;
35            parityCountC[parity]++;
36        }
37      
38        long totalValidTriplets = 0;
39      
40        // Check all combinations of parities from the three arrays
41        for (int parityA = 0; parityA < 2; parityA++) {
42            for (int parityB = 0; parityB < 2; parityB++) {
43                for (int parityC = 0; parityC < 2; parityC++) {
44                    // Sum of parities must be even for valid triplet
45                    // (even + even + even = even, odd + odd + even = even)
46                    if ((parityA + parityB + parityC) % 2 == 0) {
47                        // Multiply counts to get number of valid triplets for this parity combination
48                        totalValidTriplets += (long) parityCountA[parityA] * 
49                                              parityCountB[parityB] * 
50                                              parityCountC[parityC];
51                    }
52                }
53            }
54        }
55      
56        return totalValidTriplets;
57    }
58}
59
1class Solution {
2public:
3    long long tripletCount(vector<int>& a, vector<int>& b, vector<int>& c) {
4        // Count arrays to store the number of elements with even/odd number of set bits
5        // Index 0: count of numbers with even popcount, Index 1: count of numbers with odd popcount
6        int countA[2] = {0, 0};
7        int countB[2] = {0, 0};
8        int countC[2] = {0, 0};
9      
10        // Count elements in array 'a' based on parity of their bit count
11        for (int num : a) {
12            int bitCount = __builtin_popcount(num);  // Count number of 1s in binary representation
13            int parity = bitCount & 1;               // 0 if even, 1 if odd
14            ++countA[parity];
15        }
16      
17        // Count elements in array 'b' based on parity of their bit count
18        for (int num : b) {
19            int bitCount = __builtin_popcount(num);
20            int parity = bitCount & 1;
21            ++countB[parity];
22        }
23      
24        // Count elements in array 'c' based on parity of their bit count
25        for (int num : c) {
26            int bitCount = __builtin_popcount(num);
27            int parity = bitCount & 1;
28            ++countC[parity];
29        }
30      
31        long long result = 0;
32      
33        // Iterate through all possible combinations of parities
34        for (int parityA = 0; parityA < 2; ++parityA) {
35            for (int parityB = 0; parityB < 2; ++parityB) {
36                for (int parityC = 0; parityC < 2; ++parityC) {
37                    // Check if the sum of parities is even
38                    // This means XOR of three numbers will have even popcount
39                    if ((parityA + parityB + parityC) % 2 == 0) {
40                        // Add the product of counts for this valid combination
41                        result += 1LL * countA[parityA] * countB[parityB] * countC[parityC];
42                    }
43                }
44            }
45        }
46      
47        return result;
48    }
49};
50
1/**
2 * Counts the number of valid triplets (i, j, k) where the XOR of 
3 * a[i], b[j], and c[k] has an even number of set bits.
4 * 
5 * @param a - First array of numbers
6 * @param b - Second array of numbers  
7 * @param c - Third array of numbers
8 * @returns The count of valid triplets
9 */
10function tripletCount(a: number[], b: number[], c: number[]): number {
11    // Count arrays to store the count of numbers with even/odd bit counts
12    // Index 0: count of numbers with even number of set bits
13    // Index 1: count of numbers with odd number of set bits
14    const countArrayA: [number, number] = [0, 0];
15    const countArrayB: [number, number] = [0, 0];
16    const countArrayC: [number, number] = [0, 0];
17  
18    // Count the parity of set bits for each element in array a
19    for (const element of a) {
20        const parity = bitCount(element) & 1; // 0 for even, 1 for odd
21        ++countArrayA[parity];
22    }
23  
24    // Count the parity of set bits for each element in array b
25    for (const element of b) {
26        const parity = bitCount(element) & 1;
27        ++countArrayB[parity];
28    }
29  
30    // Count the parity of set bits for each element in array c
31    for (const element of c) {
32        const parity = bitCount(element) & 1;
33        ++countArrayC[parity];
34    }
35  
36    let totalCount = 0;
37  
38    // Check all combinations of parities
39    // XOR of three numbers has even bit count when the sum of their bit count parities is even
40    for (let parityA = 0; parityA < 2; ++parityA) {
41        for (let parityB = 0; parityB < 2; ++parityB) {
42            for (let parityC = 0; parityC < 2; ++parityC) {
43                // If sum of parities is even, XOR will have even number of set bits
44                if ((parityA + parityB + parityC) % 2 === 0) {
45                    totalCount += countArrayA[parityA] * countArrayB[parityB] * countArrayC[parityC];
46                }
47            }
48        }
49    }
50  
51    return totalCount;
52}
53
54/**
55 * Counts the number of set bits (1s) in the binary representation of a number.
56 * Uses Brian Kernighan's algorithm with bit manipulation optimizations.
57 * 
58 * @param i - The input number
59 * @returns The count of set bits
60 */
61function bitCount(i: number): number {
62    // Step 1: Count bits in groups of 2
63    i = i - ((i >>> 1) & 0x55555555);
64  
65    // Step 2: Count bits in groups of 4
66    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
67  
68    // Step 3: Count bits in groups of 8
69    i = (i + (i >>> 4)) & 0x0f0f0f0f;
70  
71    // Step 4: Count bits in groups of 16
72    i = i + (i >>> 8);
73  
74    // Step 5: Count bits in groups of 32
75    i = i + (i >>> 16);
76  
77    // Mask to get only the lowest 6 bits (max count is 32 for 32-bit integer)
78    return i & 0x3f;
79}
80

Time and Space Complexity

The time complexity is O(n), where n is the length of arrays a, b, and c. This is because:

  • Creating cnt1 requires iterating through array a to compute x.bit_count() & 1 for each element, which takes O(n) time
  • Creating cnt2 requires iterating through array b, which takes O(n) time
  • Creating cnt3 requires iterating through array c, which takes O(n) time
  • The triple nested loop iterates only through values 0 and 1 (2 iterations each), resulting in a constant 2 × 2 × 2 = 8 iterations
  • Each iteration performs constant time operations (multiplication and addition)
  • Total: O(n) + O(n) + O(n) + O(1) = O(n)

The space complexity is O(1). This is because:

  • Each Counter (cnt1, cnt2, cnt3) stores at most 2 key-value pairs (keys can only be 0 or 1, since x.bit_count() & 1 returns either 0 or 1)
  • The space used by the Counters is therefore constant, independent of input size
  • The loop variables i, j, k and ans use constant space
  • Total: O(1)

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Misunderstanding the XOR Parity Property

A common mistake is thinking that XOR of three numbers with even bit counts always results in an even bit count. This is incorrect. The parity of the XOR result depends on a more complex relationship.

Incorrect assumption:

# WRONG: Checking if all three numbers have even bit counts
if a[i].bit_count() % 2 == 0 and b[j].bit_count() % 2 == 0 and c[k].bit_count() % 2 == 0:
    count += 1

Correct approach: The XOR of three numbers has an even bit count when the sum of their individual bit count parities is even. This is because XOR operations preserve certain parity properties through the principle of linear algebra over GF(2).

2. Using Inefficient Brute Force

Another pitfall is implementing a naive O(n³) solution that checks every possible triplet:

Inefficient approach:

def tripletCount(self, a: List[int], b: List[int], c: List[int]) -> int:
    count = 0
    for i in range(len(a)):
        for j in range(len(b)):
            for k in range(len(c)):
                xor_result = a[i] ^ b[j] ^ c[k]
                if xor_result.bit_count() % 2 == 0:
                    count += 1
    return count

This approach has O(n³) time complexity and will timeout for large inputs.

Solution: Use the counting approach shown in the original solution which reduces complexity to O(n) where n is the total length of all arrays, by leveraging the mathematical property that we only need to count parities.

3. Incorrect Parity Condition Check

Some might incorrectly implement the condition for checking valid parity combinations:

Wrong implementation:

# WRONG: Using XOR instead of checking sum parity
if (parity_a ^ parity_b ^ parity_c) == 0:
    result += ...

Correct implementation:

# RIGHT: Check if sum of parities is even
if ((parity_a + parity_b + parity_c) & 1) == 0:
    result += ...

The condition should check if the sum of parities is even, not their XOR. The sum being even ensures the final XOR result has an even number of set bits.

4. Missing Edge Cases

Not handling arrays with all zeros or single elements properly:

Robust solution includes:

  • Arrays can contain zeros (which have 0 set bits, even parity)
  • Arrays can have duplicate values (counted separately in triplets)
  • Empty result when any array is empty (implicitly handled by Counter returning 0 for missing keys)
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which data structure is used to implement priority queue?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More