Facebook Pixel

3199. Count Triplets with Even XOR Set Bits I 🔒

EasyBit 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 compute the bitwise XOR of these three elements (a[i] XOR b[j] XOR c[k]), the result has an even number of set bits (1s in its binary representation).

For example, if we have:

  • a[i] = 5 (binary: 101, has 2 set bits)
  • b[j] = 3 (binary: 011, has 2 set bits)
  • c[k] = 6 (binary: 110, has 2 set bits)
  • Their XOR: 5 XOR 3 XOR 6 = 0 (binary: 000, has 0 set bits)
  • Since 0 is even, this triplet would be counted.

The key insight is that when XORing numbers, the parity (odd/even nature) of set bits in the result depends on the sum of parities of set bits in the individual numbers. If the total count of set bits across all 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 how many numbers in each array have an odd vs even number of set bits
  2. Finding all combinations where the XOR would result in an even number of set bits
  3. Using the formula that checks if (i + j + k) is even, where i, j, k represent the parity (0 for even, 1 for odd) of set bits in numbers from arrays a, b, c respectively
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

When we XOR multiple numbers together, there's a beautiful mathematical property about the parity of set bits. Let's think about what happens when we XOR two bits:

  • 0 XOR 0 = 0
  • 0 XOR 1 = 1
  • 1 XOR 0 = 1
  • 1 XOR 1 = 0

Notice that XOR essentially counts whether we have an odd or even number of 1s at each bit position. If we have an even number of 1s, the result is 0; if odd, the result is 1.

This extends to the entire number: when we XOR three numbers a[i] XOR b[j] XOR c[k], the parity of set bits in the result depends on how the set bits in the original numbers combine.

Here's the key insight: instead of computing the actual XOR for every possible triplet (which would be expensive), we can work with just the parity of set bits. If a number has an odd number of set bits, we can represent it as 1, and if it has an even number, we represent it as 0.

When XORing three numbers, the result will have an even number of set bits if and only if the sum of the parities of the three numbers is even. Why? Because:

  • If all three have even parity (0+0+0=0): even result
  • If two have odd parity and one even (1+1+0=2): even result
  • If all three have odd parity (1+1+1=3): odd result
  • If one has odd parity and two even (1+0+0=1): odd result

So we want cases where (parity_a + parity_b + parity_c) is even, which means (parity_a + parity_b + parity_c) % 2 == 0.

This transforms our problem from checking every triplet's XOR (O(n³) operations) to simply counting parities and multiplying counts (O(n) operations). We count how many numbers in each array have odd/even parity of set bits, then multiply the counts for valid parity combinations.

Solution Approach

Based on our intuition about parity, we can implement an efficient solution using counting and bit manipulation.

Step 1: Count Parities

First, we create three counters (cnt1, cnt2, cnt3) to track the parity of set bits for each number in the arrays:

  • For each number x in array a, we compute x.bit_count() & 1
    • bit_count() gives us the number of 1s in the binary representation
    • & 1 gives us the parity (0 if even, 1 if odd)
  • We do the same for arrays b and c

This gives us:

  • cnt1[0] = count of numbers in a with even number of set bits
  • cnt1[1] = count of numbers in a with odd number of set bits
  • Similarly for cnt2 and cnt3

Step 2: Enumerate Valid Combinations

We iterate through all possible parity combinations using three nested loops:

for i in range(2):      # parity from array a (0 or 1)
    for j in range(2):  # parity from array b (0 or 1)
        for k in range(2):  # parity from array c (0 or 1)

Step 3: Check Valid Parity

For each combination (i, j, k), we check if the XOR result would have an even number of set bits:

  • The condition (i + j + k) & 1 ^ 1 checks if the sum is even
    • (i + j + k) & 1 gives us the parity of the sum (0 if even, 1 if odd)
    • ^ 1 flips the bit (XOR with 1), so we get 1 if the sum is even, 0 if odd
  • When this condition is true, the XOR of any triplet with these parities will have an even number of set bits

Step 4: Count Valid Triplets

When we find a valid parity combination, we multiply the counts:

ans += cnt1[i] * cnt2[j] * cnt3[k]

This gives us the total number of triplets (a[x], b[y], c[z]) where:

  • a[x] has parity i
  • b[y] has parity j
  • c[z] has parity k

The valid combinations are:

  • (0, 0, 0): all even parities → sum = 0 (even)
  • (0, 1, 1): one even, two odd → sum = 2 (even)
  • (1, 0, 1): two odd, one even → sum = 2 (even)
  • (1, 1, 0): two odd, one even → sum = 2 (even)

Time Complexity: O(n + m + p) where n, m, p are the lengths of arrays a, b, c respectively. Space Complexity: O(1) as we only use fixed-size counters.

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 concrete example to illustrate the solution approach.

Given arrays:

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

Step 1: Analyze each number's set bits and parity

For array a:

  • 5 = binary 101 → 2 set bits → even parity (represented as 0)
  • 2 = binary 010 → 1 set bit → odd parity (represented as 1)

For array b:

  • 3 = binary 011 → 2 set bits → even parity (0)
  • 8 = binary 1000 → 1 set bit → odd parity (1)

For array c:

  • 6 = binary 110 → 2 set bits → even parity (0)
  • 1 = binary 001 → 1 set bit → odd parity (1)

Step 2: Count parities for each array

  • cnt1[0] = 1 (one number with even parity: 5)
  • cnt1[1] = 1 (one number with odd parity: 2)
  • cnt2[0] = 1 (one number with even parity: 3)
  • cnt2[1] = 1 (one number with odd parity: 8)
  • cnt3[0] = 1 (one number with even parity: 6)
  • cnt3[1] = 1 (one number with odd parity: 1)

Step 3: Find valid parity combinations

We need combinations where (i + j + k) is even:

i (parity from a)j (parity from b)k (parity from c)SumValid?Count
00001×1×1 = 1
0011-
0101-
01121×1×1 = 1
1001-
10121×1×1 = 1
11021×1×1 = 1
1113-

Step 4: Calculate total

Total valid triplets = 1 + 1 + 1 + 1 = 4

Step 5: Verify with actual triplets

Let's verify by checking all 8 possible triplets:

  1. (5, 3, 6): 5 XOR 3 XOR 6 = 0 → binary 000 → 0 set bits (even) ✓
  2. (5, 3, 1): 5 XOR 3 XOR 1 = 7 → binary 111 → 3 set bits (odd) ✗
  3. (5, 8, 6): 5 XOR 8 XOR 6 = 15 → binary 1111 → 4 set bits (even) ✓
  4. (5, 8, 1): 5 XOR 8 XOR 1 = 12 → binary 1100 → 2 set bits (even) ✓
  5. (2, 3, 6): 2 XOR 3 XOR 6 = 7 → binary 111 → 3 set bits (odd) ✗
  6. (2, 3, 1): 2 XOR 3 XOR 1 = 0 → binary 000 → 0 set bits (even) ✓
  7. (2, 8, 6): 2 XOR 8 XOR 6 = 12 → binary 1100 → 2 set bits (even) ✓
  8. (2, 8, 1): 2 XOR 8 XOR 1 = 11 → binary 1011 → 3 set bits (odd) ✗

Valid triplets: #1, #3, #4, #6 = 4 triplets

The counting approach correctly identified 4 valid triplets without computing any XOR operations, demonstrating how we can solve this problem efficiently using parity counting.

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 (odd=1, even=0) of bit counts for each array
7        # bit_count() returns the number of 1s in binary representation
8        # & 1 gives us the parity: 0 if even number of bits, 1 if 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                    # Equivalent to: (parity_a + parity_b + parity_c) % 2 == 0
21                    if ((parity_a + parity_b + parity_c) & 1) == 0:
22                        # Multiply the counts of elements with these parities
23                        result += (parity_count_a[parity_a] * 
24                                 parity_count_b[parity_b] * 
25                                 parity_count_c[parity_c])
26      
27        return result
28
1class Solution {
2    public int tripletCount(int[] a, int[] b, int[] c) {
3        // Arrays to store count of numbers with even [0] and odd [1] bit counts
4        int[] parityCountA = new int[2];
5        int[] parityCountB = new int[2];
6        int[] parityCountC = new int[2];
7      
8        // Count numbers in array 'a' by their bit count parity
9        // Index 0: even bit count, Index 1: odd bit count
10        for (int num : a) {
11            int bitCount = Integer.bitCount(num);
12            int parity = bitCount & 1;  // 0 if even, 1 if odd
13            parityCountA[parity]++;
14        }
15      
16        // Count numbers in array 'b' by their bit count parity
17        for (int num : b) {
18            int bitCount = Integer.bitCount(num);
19            int parity = bitCount & 1;
20            parityCountB[parity]++;
21        }
22      
23        // Count numbers in array 'c' by their bit count parity
24        for (int num : c) {
25            int bitCount = Integer.bitCount(num);
26            int parity = bitCount & 1;
27            parityCountC[parity]++;
28        }
29      
30        int totalTriplets = 0;
31      
32        // Check all combinations of parities from three arrays
33        // i, j, k represent parities (0 = even, 1 = odd)
34        for (int i = 0; i < 2; i++) {
35            for (int j = 0; j < 2; j++) {
36                for (int k = 0; k < 2; k++) {
37                    // Count triplets where sum of bit count parities is even
38                    // This happens when: all even (0+0+0), or one even and two odd (0+1+1)
39                    if ((i + j + k) % 2 == 0) {
40                        totalTriplets += parityCountA[i] * parityCountB[j] * parityCountC[k];
41                    }
42                }
43            }
44        }
45      
46        return totalTriplets;
47    }
48}
49
1class Solution {
2public:
3    int tripletCount(vector<int>& a, vector<int>& b, vector<int>& c) {
4        // Count elements by parity of their bit count (even=0, odd=1)
5        int parityCountA[2] = {0, 0};
6        int parityCountB[2] = {0, 0};
7        int parityCountC[2] = {0, 0};
8      
9        // Count elements in array 'a' by bit count parity
10        for (int num : a) {
11            int bitCount = __builtin_popcount(num);
12            int parity = bitCount & 1;  // 0 if even, 1 if odd
13            ++parityCountA[parity];
14        }
15      
16        // Count elements in array 'b' by bit count parity
17        for (int num : b) {
18            int bitCount = __builtin_popcount(num);
19            int parity = bitCount & 1;
20            ++parityCountB[parity];
21        }
22      
23        // Count elements in array 'c' by bit count parity
24        for (int num : c) {
25            int bitCount = __builtin_popcount(num);
26            int parity = bitCount & 1;
27            ++parityCountC[parity];
28        }
29      
30        int result = 0;
31      
32        // Try all combinations of parities from the three arrays
33        for (int parityA = 0; parityA < 2; ++parityA) {
34            for (int parityB = 0; parityB < 2; ++parityB) {
35                for (int parityC = 0; parityC < 2; ++parityC) {
36                    // Check if sum of parities is even
37                    if ((parityA + parityB + parityC) % 2 == 0) {
38                        // Count valid triplets with this parity combination
39                        result += parityCountA[parityA] * 
40                                 parityCountB[parityB] * 
41                                 parityCountC[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 numbers with even/odd bit counts in array a
19    for (const num of a) {
20        const bitParity = bitCount(num) & 1; // 0 for even, 1 for odd
21        ++countArrayA[bitParity];
22    }
23  
24    // Count numbers with even/odd bit counts in array b
25    for (const num of b) {
26        const bitParity = bitCount(num) & 1;
27        ++countArrayB[bitParity];
28    }
29  
30    // Count numbers with even/odd bit counts in array c
31    for (const num of c) {
32        const bitParity = bitCount(num) & 1;
33        ++countArrayC[bitParity];
34    }
35  
36    let totalCount = 0;
37  
38    // Check all combinations of even/odd bit counts
39    // XOR of three numbers has even bit count when the sum of their bit parities is even
40    for (let i = 0; i < 2; ++i) {
41        for (let j = 0; j < 2; ++j) {
42            for (let k = 0; k < 2; ++k) {
43                // If sum of parities is even, the XOR will have even number of set bits
44                if ((i + j + k) % 2 === 0) {
45                    totalCount += countArrayA[i] * countArrayB[j] * countArrayC[k];
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 number to count bits for
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    // Return the final count (max 32 bits, so mask with 0x3f)
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 exactly 2×2×2 = 8 times (constant), and each iteration performs constant-time operations (dictionary lookups and multiplication)
  • Overall: 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 constant regardless of input size
  • The variable ans and loop variables i, j, k use constant space
  • Overall: O(1)

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

Common Pitfalls

1. Misunderstanding XOR Parity Property

Pitfall: Assuming that XOR of three numbers with even bit counts always results in an even bit count.

Example:

  • a = 3 (binary: 011, 2 set bits - even)
  • b = 5 (binary: 101, 2 set bits - even)
  • c = 6 (binary: 110, 2 set bits - even)
  • 3 XOR 5 XOR 6 = 0 (binary: 000, 0 set bits - even) ✓

But consider:

  • a = 3 (binary: 011, 2 set bits - even)
  • b = 3 (binary: 011, 2 set bits - even)
  • c = 0 (binary: 000, 0 set bits - even)
  • 3 XOR 3 XOR 0 = 0 (binary: 000, 0 set bits - even) ✓

The rule isn't about individual parities but their sum modulo 2.

2. Integer Overflow in Large Arrays

Pitfall: When arrays are large, the multiplication cnt1[i] * cnt2[j] * cnt3[k] might overflow in languages with fixed integer sizes.

Solution: In Python this isn't an issue due to arbitrary precision integers, but in other languages:

# Use long/int64 or modular arithmetic if needed
result = (result + (cnt1[i] * cnt2[j] % MOD * cnt3[k]) % MOD) % MOD

3. Incorrect Parity Check Logic

Pitfall: Writing the condition as (i + j + k) & 1 ^ 1 which evaluates as ((i + j + k) & 1) ^ 1 due to operator precedence, when you might intend (i + j + k) & (1 ^ 1).

Solution: Be explicit with the condition:

# Clear and readable
if (parity_a + parity_b + parity_c) % 2 == 0:
    # Process valid combination

# Or using bitwise operations
if ((parity_a + parity_b + parity_c) & 1) == 0:
    # Process valid combination

4. Missing Edge Cases

Pitfall: Not handling arrays with all zeros or single elements properly.

Example Issue:

# Arrays with zeros
a = [0, 0, 0]  # All have 0 set bits (even)
b = [1]        # Has 1 set bit (odd)
c = [1]        # Has 1 set bit (odd)
# 0 XOR 1 XOR 1 = 0 (0 set bits - even)
# Should count 3 triplets

Solution: The current approach handles this correctly since 0.bit_count() = 0 (even parity), but always verify with test cases.

5. Using Wrong Bit Counting Method

Pitfall: In older Python versions or other languages, bit_count() might not be available.

Solution: Implement a helper function:

def count_bits(n):
    count = 0
    while n:
        count += n & 1
        n >>= 1
    return count

# Or use bin() function
def count_bits_alt(n):
    return bin(n).count('1')

# Then use in main logic
parity_count_a = Counter(count_bits(x) & 1 for x in a)

6. Confusion About Valid Parity Combinations

Pitfall: Forgetting why only certain parity combinations work.

Clarification: The XOR result has even set bits when:

  • All three numbers have even parity (0+0+0=0, even)
  • One has even parity, two have odd parity (0+1+1=2, even)

Invalid combinations:

  • All three have odd parity (1+1+1=3, odd)
  • Two have even, one has odd (0+0+1=1, odd)
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What are the two properties the problem needs to have for dynamic programming to be applicable? (Select 2)


Recommended Readings

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

Load More