3199. Count Triplets with Even XOR Set Bits I 🔒
Problem Description
Given three integer arrays a
, b
, and c
, you need to determine the number of triplets (a[i], b[j], c[k])
such that the bitwise XOR
of these elements results in a number with an even number of set bits. A set bit is a 1 in the binary representation of the number. Your task is to return this count.
Intuition
To solve this problem, we begin by understanding how the bitwise XOR
operates. The critical observation is that the parity (even or odd nature) of the count of set bits in the result of an XOR
operation depends on the parity of the count of set bits in the individual numbers involved.
-
Bit Count & Parity: For each number in the arrays
a
,b
, andc
, determine whether the number of set bits in its binary form is even or odd. This will help us to keep track of the parity of set bits usingbit_count() & 1
which results in0
for even and1
for odd. -
Count Parity Types: Use counters to tally how many numbers in each array have an even number of set bits and how many have an odd number of set bits. This facilitates quick access when calculating the desired number of triplets.
-
Constructing Triplets: Iterate over all combinations of parities from the three arrays (i.e., even or odd, represented by
0
or1
). For each combination, check if the sum of these parities results in an even number. If so, the total number of set bits in theXOR
would be even as requested. -
Calculate Results: For valid combinations (where the sum of parities is even), multiply their counts from the respective arrays and sum these products to get the total number of qualifying triplets.
By systematically applying these insights, you can efficiently determine the number of triplets that satisfy the problem's criteria without directly computing the XOR
for every possible triplet.
Solution Approach
To implement the solution, the approach leverages bit manipulation techniques along with counting data structures. Here's a detailed walkthrough of the algorithm and data structures used:
-
Counting Parity with Counters:
- Use the
Counter
from thecollections
module to track the parity of the number of set bits (0 for even, 1 for odd) in each number of the arraysa
,b
, andc
. - Utilize the expression
x.bit_count() & 1
to compute the parity of set bits for each elementx
.
cnt1 = Counter(x.bit_count() & 1 for x in a) cnt2 = Counter(x.bit_count() & 1 for x in b) cnt3 = Counter(x.bit_count() & 1 for x in c)
- Use the
-
Iterate Over Parity Combinations:
- There are only two states for parity (even and odd), represented by
0
and1
. Iterate over all possible combinations of parities for numbers from arraysa
,b
, andc
. - Use nested loops to cover combinations:
(i, j, k)
wherei
,j
,k
can be either0
or1
.
for i in range(2): for j in range(2): for k in range(2):
- There are only two states for parity (even and odd), represented by
-
Conditional Check and Accumulation:
- If the sum of
i
,j
, andk
is even (checking using(i + j + k) & 1 ^ 1
), multiply the counts of the respective parity from each array and add to the answer accumulatorans
.
if (i + j + k) & 1 ^ 1: ans += cnt1[i] * cnt2[j] * cnt3[k]
- If the sum of
-
Return Result:
- After tallying all valid combinations, return
ans
which contains the total number of qualifying triplets.
return ans
- After tallying all valid combinations, return
This approach is efficient because it avoids the need for a triple nested loop over all elements of a
, b
, and c
, instead iterating only over parity combinations and leveraging the mathematical properties of XOR and binary representations.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider a small example to illustrate the solution approach:
Suppose we have three arrays:
a = [3, 5]
b = [7, 1]
c = [6, 2]
Step 1: Counting Parity with Counters
-
For array
a
, convert each element's binary form:3
in binary is11
, which has 2 set bits (even), so parity is0
.5
in binary is101
, which has 2 set bits (even), so parity is0
.
cnt1 = Counter({0: 2})
because both3
and5
have even parity. -
For array
b
:7
in binary is111
, which has 3 set bits (odd), so parity is1
.1
in binary is1
, which has 1 set bit (odd), so parity is1
.
cnt2 = Counter({1: 2})
because both7
and1
have odd parity. -
For array
c
:6
in binary is110
, which has 2 set bits (even), so parity is0
.2
in binary is10
, which has 1 set bit (odd), so parity is1
.
cnt3 = Counter({0: 1, 1: 1})
as6
has even and2
has odd parity.
Step 2: Iterate Over Parity Combinations
- Iterate over combinations of
i
,j
,k
where each can be0
or1
, and compute if the combination results in an even sum of set bits using(i + j + k) & 1 ^ 1
.
Step 3: Conditional Check and Accumulation
- Check combinations:
i = 0, j = 1, k = 1
:(0 + 1 + 1) & 1 ^ 1 = 0
, not valid.i = 0, j = 1, k = 0
:(0 + 1 + 0) & 1 ^ 1 = 1
, valid. Count this ascnt1[0] * cnt2[1] * cnt3[0] = 2 * 2 * 1 = 4
.- Similarly check and find combinations.
After all combinations, the valid triplets are those resulting in i + j + k
being even.
Step 4: Return Result
- After accumulating valid triplet counts, the answer
ans
is4
.
Thus, for the example, there are 4 triplets that meet the criteria.
Solution Implementation
1from collections import Counter
2from typing import List
3
4class Solution:
5 def tripletCount(self, a: List[int], b: List[int], c: List[int]) -> int:
6 # Count how many numbers in each list have an odd or even number of 1s in their binary representation
7 count_a = Counter(x.bit_count() & 1 for x in a)
8 count_b = Counter(x.bit_count() & 1 for x in b)
9 count_c = Counter(x.bit_count() & 1 for x in c)
10
11 result = 0
12
13 # Iterate over all possible combinations of parity (odd/even)
14 for i in range(2): # i can be 0 (even) or 1 (odd)
15 for j in range(2): # j can be 0 (even) or 1 (odd)
16 for k in range(2): # k can be 0 (even) or 1 (odd)
17 # Check if the sum is even
18 if (i + j + k) & 1 == 0:
19 # Increment the result by the product of the counts for this combination
20 result += count_a[i] * count_b[j] * count_c[k]
21
22 return result
23
1class Solution {
2 public int tripletCount(int[] a, int[] b, int[] c) {
3 // Arrays to count the number of integers with even and odd number of set bits in each array
4 int[] countA = new int[2];
5 int[] countB = new int[2];
6 int[] countC = new int[2];
7
8 // Count the number of integers with odd and even number of 1-bits for array a
9 for (int x : a) {
10 int bitCount = Integer.bitCount(x) & 1;
11 ++countA[bitCount];
12 }
13
14 // Count the number of integers with odd and even number of 1-bits for array b
15 for (int x : b) {
16 int bitCount = Integer.bitCount(x) & 1;
17 ++countB[bitCount];
18 }
19
20 // Count the number of integers with odd and even number of 1-bits for array c
21 for (int x : c) {
22 int bitCount = Integer.bitCount(x) & 1;
23 ++countC[bitCount];
24 }
25
26 int result = 0;
27
28 // Iterate through all possible combinations of counts (even=0, odd=1)
29 for (int i = 0; i < 2; ++i) {
30 for (int j = 0; j < 2; ++j) {
31 for (int k = 0; k < 2; ++k) {
32 // Check if the sum of indices is even
33 if ((i + j + k) % 2 == 0) {
34 // Add the product of counts for the current combination to the result
35 result += countA[i] * countB[j] * countC[k];
36 }
37 }
38 }
39 }
40
41 return result;
42 }
43}
44
1#include <vector>
2
3class Solution {
4public:
5 int tripletCount(std::vector<int>& a, std::vector<int>& b, std::vector<int>& c) {
6 // Initialize counters for even and odd popcounts
7 int cntA[2] = {};
8 int cntB[2] = {};
9 int cntC[2] = {};
10
11 // Count how many numbers in 'a' have even and odd popcounts
12 for (int num : a) {
13 ++cntA[__builtin_popcount(num) & 1];
14 }
15
16 // Count how many numbers in 'b' have even and odd popcounts
17 for (int num : b) {
18 ++cntB[__builtin_popcount(num) & 1];
19 }
20
21 // Count how many numbers in 'c' have even and odd popcounts
22 for (int num : c) {
23 ++cntC[__builtin_popcount(num) & 1];
24 }
25
26 int result = 0;
27
28 // Calculate the number of valid triplets (a, b, c) such that
29 // the sum of popcounts' parities is even
30 for (int i = 0; i < 2; ++i) {
31 for (int j = 0; j < 2; ++j) {
32 for (int k = 0; k < 2; ++k) {
33 if ((i + j + k) % 2 == 0) {
34 result += cntA[i] * cntB[j] * cntC[k];
35 }
36 }
37 }
38 }
39
40 return result;
41 }
42};
43
1// This function calculates the number of valid triplets (x, y, z) such that the sum of bits is even.
2function tripletCount(a: number[], b: number[], c: number[]): number {
3 // Initialize counters for odd and even bit-count elements in each array.
4 const cnt1: [number, number] = [0, 0];
5 const cnt2: [number, number] = [0, 0];
6 const cnt3: [number, number] = [0, 0];
7
8 // Populate cnt1 with parity counts for array 'a'.
9 for (const x of a) {
10 cnt1[bitCount(x) & 1]++;
11 }
12
13 // Populate cnt2 with parity counts for array 'b'.
14 for (const x of b) {
15 cnt2[bitCount(x) & 1]++;
16 }
17
18 // Populate cnt3 with parity counts for array 'c'.
19 for (const x of c) {
20 cnt3[bitCount(x) & 1]++;
21 }
22
23 let ans = 0;
24
25 // Check each combination of parity (odd/even) counts and accumulate the number of triplets
26 // where the sum of bits is even.
27 for (let i = 0; i < 2; ++i) {
28 for (let j = 0; j < 2; ++j) {
29 for (let k = 0; k < 2; ++k) {
30 if ((i + j + k) % 2 === 0) {
31 ans += cnt1[i] * cnt2[j] * cnt3[k];
32 }
33 }
34 }
35 }
36
37 return ans; // Return the total count of valid triplets.
38}
39
40// This function calculates the number of set bits (1s) in the binary representation of an integer.
41function bitCount(value: number): number {
42 // Use bit manipulation techniques to efficiently count set bits.
43 value = value - ((value >>> 1) & 0x55555555);
44 value = (value & 0x33333333) + ((value >>> 2) & 0x33333333);
45 value = (value + (value >>> 4)) & 0x0f0f0f0f;
46 value = value + (value >>> 8);
47 value = value + (value >>> 16);
48 return value & 0x3f; // Mask to get the final count of set bits.
49}
50
Time and Space Complexity
The time complexity of the code is O(n)
, where n
is the combined length of arrays a
, b
, and c
. This is because each element in these arrays is processed exactly once to calculate the bit count parity and to populate the counters.
The space complexity of the code is O(1)
. The Counter
objects cnt1
, cnt2
, and cnt3
only store counts for at most 2 distinct values (0 or 1) based on the parity of the bit count, meaning they do not grow with the size of the input arrays.
Learn more about how to find time and space complexity quickly.
How many ways can you arrange the three letters A, B and C?
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 algomonster s3 us east 2 amazonaws com recursion jpg You first
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!