3199. Count Triplets with Even XOR Set Bits I 🔒
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:
- Counting how many numbers in each array have an odd vs even number of set bits
- Finding all combinations where the XOR would result in an even number of set bits
- Using the formula that checks if
(i + j + k)
is even, wherei
,j
,k
represent the parity (0 for even, 1 for odd) of set bits in numbers from arraysa
,b
,c
respectively
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 arraya
, we computex.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
andc
This gives us:
cnt1[0]
= count of numbers ina
with even number of set bitscnt1[1]
= count of numbers ina
with odd number of set bits- Similarly for
cnt2
andcnt3
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 parityi
b[y]
has parityj
c[z]
has parityk
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 EvaluatorExample 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
= binary101
→ 2 set bits → even parity (represented as 0)2
= binary010
→ 1 set bit → odd parity (represented as 1)
For array b
:
3
= binary011
→ 2 set bits → even parity (0)8
= binary1000
→ 1 set bit → odd parity (1)
For array c
:
6
= binary110
→ 2 set bits → even parity (0)1
= binary001
→ 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) | Sum | Valid? | Count |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | ✓ | 1×1×1 = 1 |
0 | 0 | 1 | 1 | ✗ | - |
0 | 1 | 0 | 1 | ✗ | - |
0 | 1 | 1 | 2 | ✓ | 1×1×1 = 1 |
1 | 0 | 0 | 1 | ✗ | - |
1 | 0 | 1 | 2 | ✓ | 1×1×1 = 1 |
1 | 1 | 0 | 2 | ✓ | 1×1×1 = 1 |
1 | 1 | 1 | 3 | ✗ | - |
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:
(5, 3, 6)
:5 XOR 3 XOR 6 = 0
→ binary000
→ 0 set bits (even) ✓(5, 3, 1)
:5 XOR 3 XOR 1 = 7
→ binary111
→ 3 set bits (odd) ✗(5, 8, 6)
:5 XOR 8 XOR 6 = 15
→ binary1111
→ 4 set bits (even) ✓(5, 8, 1)
:5 XOR 8 XOR 1 = 12
→ binary1100
→ 2 set bits (even) ✓(2, 3, 6)
:2 XOR 3 XOR 6 = 7
→ binary111
→ 3 set bits (odd) ✗(2, 3, 1)
:2 XOR 3 XOR 1 = 0
→ binary000
→ 0 set bits (even) ✓(2, 8, 6)
:2 XOR 8 XOR 6 = 12
→ binary1100
→ 2 set bits (even) ✓(2, 8, 1)
:2 XOR 8 XOR 1 = 11
→ binary1011
→ 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 arraya
to computex.bit_count() & 1
for each element, which takesO(n)
time - Creating
cnt2
requires iterating through arrayb
, which takesO(n)
time - Creating
cnt3
requires iterating through arrayc
, which takesO(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, sincex.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 variablesi
,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)
What are the two properties the problem needs to have for dynamic programming to be applicable? (Select 2)
Recommended Readings
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
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!