2595. Number of Even and Odd Bits
Problem Description
You are given a positive integer n
. Your task is to count how many 1
bits appear at even positions and how many appear at odd positions in the binary representation of n
.
The binary representation is indexed from right to left, starting at index 0. This means:
- The rightmost bit (least significant bit) is at index 0 (even)
- The second bit from the right is at index 1 (odd)
- The third bit from the right is at index 2 (even)
- And so on...
You need to:
- Count all the
1
bits that appear at even indices (0, 2, 4, ...) - store this aseven
- Count all the
1
bits that appear at odd indices (1, 3, 5, ...) - store this asodd
- Return the result as an array
[even, odd]
For example, if n = 13
:
- Binary representation:
1101
- Index positions (right to left): indices 3, 2, 1, 0 correspond to bits 1, 1, 0, 1
- Bits at even indices (0, 2): both are
1
, soeven = 2
- Bits at odd indices (1, 3): index 1 has
0
and index 3 has1
, soodd = 1
- Return
[2, 1]
The solution iterates through each bit of n
from right to left. It uses n & 1
to check if the current least significant bit is 1
, adds it to the appropriate counter based on whether the current position is even or odd (tracked by variable i
which alternates between 0 and 1 using XOR operation), then shifts n
right by one position to process the next bit.
Intuition
The key insight is that we need to process the binary representation of n
bit by bit, keeping track of whether each bit position is even or odd.
Since we're indexing from right to left starting at 0, we can process the number from its least significant bit (rightmost) to its most significant bit (leftmost). This naturally aligns with how we can extract bits from a number using bitwise operations.
The most straightforward way to extract bits one by one is:
- Use
n & 1
to get the current least significant bit (0 or 1) - Use
n >> 1
to shift the number right, making the next bit become the least significant bit
As we process each bit, we need to know if we're at an even or odd index. Instead of maintaining a separate counter that we increment and check with modulo operation (index % 2
), we can use a clever alternating pattern. We start with index 0 (even), then 1 (odd), then 0 (even), and so on.
This alternating pattern can be elegantly achieved using XOR: i ^= 1
. Starting with i = 0
:
0 ^ 1 = 1
(switches to odd)1 ^ 1 = 0
(switches back to even)- This continues alternating between 0 and 1
By using ans[i]
where i
alternates between 0 and 1, we automatically add to ans[0]
(even count) when at even positions and ans[1]
(odd count) when at odd positions. The value n & 1
gives us either 0 or 1, which is exactly what we want to add to our counter.
The loop continues until n
becomes 0, meaning we've processed all the bits that were set to 1 (we don't need to count leading zeros).
Solution Approach
The solution uses a bit manipulation approach to enumerate through the binary representation of n
from the least significant bit to the most significant bit.
Implementation Steps:
-
Initialize counters: Create an array
ans = [0, 0]
whereans[0]
will store the count of1
s at even indices andans[1]
will store the count of1
s at odd indices. -
Set position tracker: Initialize
i = 0
to track whether we're currently at an even (0) or odd (1) position. -
Process bits iteratively: Use a while loop that continues as long as
n > 0
:a. Extract current bit: Use
n & 1
to get the least significant bit. This operation returns1
if the bit is set,0
otherwise.b. Update counter: Add the extracted bit value to
ans[i]
. Sincei
alternates between 0 and 1, this automatically adds to the correct counter:- When
i = 0
, we add to the even counter - When
i = 1
, we add to the odd counter
c. Toggle position: Use
i ^= 1
to flip between even (0) and odd (1) positions. The XOR operation with 1 toggles the value:0 ^ 1 = 1
1 ^ 1 = 0
d. Shift to next bit: Use
n >>= 1
to right-shiftn
by one position, effectively removing the processed bit and bringing the next bit to the least significant position. - When
-
Return result: Once all bits are processed (when
n
becomes 0), return theans
array containing[even_count, odd_count]
.
Example walkthrough with n = 13
(binary: 1101
):
- Initial:
ans = [0, 0]
,i = 0
,n = 1101
- Iteration 1: bit =
1
,ans[0] += 1
→ans = [1, 0]
,i = 1
,n = 110
- Iteration 2: bit =
0
,ans[1] += 0
→ans = [1, 0]
,i = 0
,n = 11
- Iteration 3: bit =
1
,ans[0] += 1
→ans = [2, 0]
,i = 1
,n = 1
- Iteration 4: bit =
1
,ans[1] += 1
→ans = [2, 1]
,i = 0
,n = 0
- Return
[2, 1]
The time complexity is O(log n)
as we process each bit of n
, and the space complexity is O(1)
as we only use a fixed-size array and a few variables.
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 n = 23
(binary: 10111
).
We'll track the binary representation from right to left with indices:
Binary: 1 0 1 1 1 Index: 4 3 2 1 0 Type: even odd even odd even
Initial Setup:
ans = [0, 0]
whereans[0]
counts 1s at even positions,ans[1]
counts 1s at odd positionsi = 0
(starting at even position)n = 23
(binary:10111
)
Iteration 1:
- Current bit:
n & 1 = 10111 & 1 = 1
(rightmost bit) - Position:
i = 0
(even), so we add toans[0]
- Update:
ans[0] += 1
→ans = [1, 0]
- Toggle position:
i ^= 1
→i = 1
- Shift right:
n >>= 1
→n = 1011
Iteration 2:
- Current bit:
n & 1 = 1011 & 1 = 1
- Position:
i = 1
(odd), so we add toans[1]
- Update:
ans[1] += 1
→ans = [1, 1]
- Toggle position:
i ^= 1
→i = 0
- Shift right:
n >>= 1
→n = 101
Iteration 3:
- Current bit:
n & 1 = 101 & 1 = 1
- Position:
i = 0
(even), so we add toans[0]
- Update:
ans[0] += 1
→ans = [2, 1]
- Toggle position:
i ^= 1
→i = 1
- Shift right:
n >>= 1
→n = 10
Iteration 4:
- Current bit:
n & 1 = 10 & 1 = 0
- Position:
i = 1
(odd), so we add toans[1]
- Update:
ans[1] += 0
→ans = [2, 1]
(no change since bit is 0) - Toggle position:
i ^= 1
→i = 0
- Shift right:
n >>= 1
→n = 1
Iteration 5:
- Current bit:
n & 1 = 1 & 1 = 1
- Position:
i = 0
(even), so we add toans[0]
- Update:
ans[0] += 1
→ans = [3, 1]
- Toggle position:
i ^= 1
→i = 1
- Shift right:
n >>= 1
→n = 0
Result:
- Loop ends since
n = 0
- Return
[3, 1]
This matches our expectation: positions 0, 2, and 4 (even) have 1s, while only position 1 (odd) has a 1.
Solution Implementation
1class Solution:
2 def evenOddBit(self, n: int) -> List[int]:
3 """
4 Count the number of 1s at even and odd bit positions in binary representation.
5
6 Args:
7 n: A positive integer
8
9 Returns:
10 A list [even_count, odd_count] where:
11 - even_count: number of 1s at even positions (0, 2, 4, ...)
12 - odd_count: number of 1s at odd positions (1, 3, 5, ...)
13 """
14 # Initialize counters for even and odd positions
15 result = [0, 0] # [even_position_count, odd_position_count]
16
17 # Track current bit position (0 for even, 1 for odd)
18 position_index = 0
19
20 # Process each bit from right to left
21 while n > 0:
22 # Check if the current bit is 1 and increment corresponding counter
23 result[position_index] += n & 1
24
25 # Toggle between even (0) and odd (1) positions
26 position_index ^= 1
27
28 # Right shift to process the next bit
29 n >>= 1
30
31 return result
32
1class Solution {
2 public int[] evenOddBit(int n) {
3 // Initialize result array: index 0 for even positions, index 1 for odd positions
4 int[] result = new int[2];
5
6 // Process each bit of n from right to left
7 // i tracks current position parity (0 for even, 1 for odd)
8 for (int positionParity = 0; n > 0; n >>= 1, positionParity ^= 1) {
9 // Extract the least significant bit and add to corresponding counter
10 // When positionParity is 0, we're at an even position (0, 2, 4, ...)
11 // When positionParity is 1, we're at an odd position (1, 3, 5, ...)
12 result[positionParity] += n & 1;
13 }
14
15 // Return array with [evenBitCount, oddBitCount]
16 return result;
17 }
18}
19
1class Solution {
2public:
3 vector<int> evenOddBit(int n) {
4 // Initialize result vector with 2 elements (both 0)
5 // ans[0] will store count of 1s at even positions (0, 2, 4, ...)
6 // ans[1] will store count of 1s at odd positions (1, 3, 5, ...)
7 vector<int> ans(2);
8
9 // Process each bit of n from right to left (LSB to MSB)
10 // i tracks whether current bit position is even (0) or odd (1)
11 for (int i = 0; n > 0; n >>= 1, i ^= 1) {
12 // Check if the rightmost bit is 1
13 // If yes, increment the count at the appropriate position (even/odd)
14 ans[i] += n & 1;
15 }
16
17 return ans;
18 }
19};
20
1/**
2 * Counts the number of 1-bits at even and odd positions in the binary representation of n
3 * @param n - The input number to analyze
4 * @returns An array where [evenCount, oddCount] representing 1-bits at even/odd positions
5 */
6function evenOddBit(n: number): number[] {
7 // Initialize result array with [evenCount, oddCount] both set to 0
8 const result: number[] = Array(2).fill(0);
9
10 // Iterate through each bit of n from right to left (LSB to MSB)
11 // i tracks whether we're at an even (0) or odd (1) position
12 for (let bitPosition: number = 0; n > 0; n >>= 1, bitPosition ^= 1) {
13 // Check if the current bit is 1 and increment the corresponding counter
14 // bitPosition alternates between 0 and 1 due to XOR operation
15 result[bitPosition] += n & 1;
16 }
17
18 return result;
19}
20
Time and Space Complexity
Time Complexity: O(log n)
The algorithm iterates through each bit of the binary representation of n
. In each iteration:
- It checks the least significant bit using
n & 1
-O(1)
operation - It toggles the index using
i ^= 1
-O(1)
operation - It right shifts
n
by 1 position usingn >>= 1
-O(1)
operation
The while loop continues until n
becomes 0, which happens after processing all bits in the binary representation of n
. Since an integer n
has ⌊log₂ n⌋ + 1
bits in its binary representation, the loop runs O(log n)
times.
Space Complexity: O(1)
The algorithm uses only a constant amount of extra space:
ans
list with exactly 2 elements -O(1)
- Variable
i
to track the current index -O(1)
The space usage doesn't grow with the input size n
, making the space complexity constant.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Misunderstanding the Index Direction
Pitfall: A common mistake is assuming the binary representation is indexed from left to right (most significant bit first). This leads to incorrect counting as developers might process the bits in the wrong order or assign them to wrong position categories.
Example of incorrect approach:
# WRONG: Converting to string and indexing from left
binary_str = bin(n)[2:] # "1101" for n=13
for i, bit in enumerate(binary_str):
if bit == '1':
if i % 2 == 0:
even += 1 # This incorrectly treats leftmost bit as index 0
Solution: Always remember that bit positions are counted from right to left (LSB to MSB). The rightmost bit is at index 0. Using bit manipulation with right shift ensures correct processing order.
2. Incorrect Position Tracking Initialization
Pitfall: Starting the position index at 1 instead of 0, thinking the first position should be 1-indexed.
Example of incorrect code:
position_index = 1 # WRONG: Should start at 0 for even position while n > 0: result[position_index] += n & 1 position_index ^= 1 n >>= 1
Solution: Initialize position_index = 0
since the rightmost bit (LSB) is at index 0, which is an even position.
3. Using Modulo Instead of XOR for Position Toggle
Pitfall: While using position_index = (position_index + 1) % 2
works correctly, it's less efficient than XOR and might lead to confusion or errors if modified incorrectly.
Less optimal approach:
position_index = 0 while n > 0: result[position_index] += n & 1 position_index = (position_index + 1) % 2 # Works but less efficient n >>= 1
Solution: Use position_index ^= 1
for cleaner and more efficient toggling between 0 and 1.
4. Off-by-One Error in Result Array
Pitfall: Confusing the array indices with the actual even/odd positions, potentially swapping the results.
Example of confusion:
# Accidentally returning [odd_count, even_count] instead of [even_count, odd_count] result = [0, 0] # ... processing logic ... return [result[1], result[0]] # WRONG: Swapped order
Solution: Maintain clear variable naming and remember that result[0]
stores even position counts and result[1]
stores odd position counts. The position_index directly corresponds to the array index.
5. Forgetting Edge Cases
Pitfall: Not considering that n
could be 0 (though the problem states positive integer) or very large numbers.
Solution: The current implementation handles all positive integers correctly. If extending to handle 0, the function would correctly return [0, 0]
without modification.
What data structure does Breadth-first search typically uses to store intermediate states?
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!