1523. Count Odd Numbers in an Interval Range
Problem Description
Given two non-negative integers low
and high
, you need to count how many odd numbers exist between these two values, including both low
and high
if they are odd.
For example:
- If
low = 3
andhigh = 7
, the odd numbers in this range are [3, 5, 7], so the count is 3 - If
low = 8
andhigh = 10
, the odd numbers in this range are [9], so the count is 1
The solution uses a clever bit manipulation approach. The expression (high + 1) >> 1
counts how many odd numbers exist from 0 up to high
, and low >> 1
counts how many odd numbers exist from 0 up to low - 1
. The difference between these two values gives us the count of odd numbers in the range [low, high]
.
The key insight is that right-shifting by 1 (dividing by 2) gives us the count of odd numbers up to a certain point:
- For any number
n
, there are(n + 1) / 2
odd numbers from 0 ton
(inclusive) - By subtracting the count of odds before
low
from the count of odds up tohigh
, we get the desired result
Intuition
To count odd numbers in a range, we can observe a pattern: odd numbers appear at regular intervals. In any sequence starting from 0, odd numbers occur at positions 1, 3, 5, 7, and so on.
If we look at the range from 0 to any number n
:
- From 0 to 1: we have 1 odd number (which is 1)
- From 0 to 2: we have 1 odd number (which is 1)
- From 0 to 3: we have 2 odd numbers (1 and 3)
- From 0 to 4: we have 2 odd numbers (1 and 3)
- From 0 to 5: we have 3 odd numbers (1, 3, and 5)
Notice the pattern: for any number n
, the count of odd numbers from 0 to n
is (n + 1) / 2
when using integer division. This makes sense because roughly half of all numbers are odd, and we need to account for whether n
itself is odd or even.
Now, to find odd numbers in a range [low, high]
, we can use the principle of subtraction: instead of counting directly in the range, we can count all odds from 0 to high
, then subtract the odds from 0 to low - 1
.
The formula becomes: count(0 to high) - count(0 to low-1)
Since count(0 to n) = (n + 1) / 2
, we get:
- Count from 0 to
high
=(high + 1) / 2
- Count from 0 to
low - 1
=low / 2
Therefore, the answer is (high + 1) / 2 - low / 2
, which in the code is implemented using right shift operations (>> 1
) for efficient division by 2.
Learn more about Math patterns.
Solution Approach
The solution implements a mathematical formula using bit manipulation for efficiency. Let's break down the implementation step by step:
Mathematical Formula:
The core formula is: ((high + 1) >> 1) - (low >> 1)
Step-by-step breakdown:
-
Calculate odd numbers from 0 to high:
(high + 1) >> 1
computes the count of odd numbers from 0 tohigh
(inclusive)- The right shift by 1 (
>> 1
) is equivalent to integer division by 2 - Adding 1 to
high
before dividing ensures we count correctly whenhigh
is odd
-
Calculate odd numbers from 0 to low-1:
low >> 1
computes the count of odd numbers from 0 tolow - 1
(inclusive)- This gives us the count of odd numbers that come before our range
-
Subtract to get the final count:
- The difference between these two values gives us exactly the count of odd numbers in
[low, high]
- The difference between these two values gives us exactly the count of odd numbers in
Why this works:
- When we right-shift an even number by 1, we get the exact count of odd numbers before it
- When we right-shift an odd number by 1, we get the count of odd numbers before it (not including itself)
- By using
(high + 1) >> 1
, we ensure that ifhigh
is odd, it gets counted - By using
low >> 1
, we ensure that iflow
is odd, it's not excluded from our range
Example walkthrough:
If low = 3
and high = 7
:
(7 + 1) >> 1 = 8 >> 1 = 4
(odd numbers from 0 to 7: 1, 3, 5, 7)3 >> 1 = 1
(odd numbers from 0 to 2: 1)- Result:
4 - 1 = 3
(odd numbers in range: 3, 5, 7)
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 the solution with low = 5
and high = 11
.
Step 1: Identify the odd numbers in our range The odd numbers between 5 and 11 (inclusive) are: [5, 7, 9, 11] - so we expect our answer to be 4.
Step 2: Calculate odd numbers from 0 to high (11)
- We compute
(high + 1) >> 1 = (11 + 1) >> 1 = 12 >> 1 = 6
- This represents the odd numbers from 0 to 11: [1, 3, 5, 7, 9, 11] - indeed 6 numbers
Step 3: Calculate odd numbers from 0 to low-1 (4)
- We compute
low >> 1 = 5 >> 1 = 2
- This represents the odd numbers from 0 to 4: [1, 3] - indeed 2 numbers
Step 4: Find the difference
- Result = 6 - 2 = 4
- This gives us the count of odd numbers in [5, 11]: [5, 7, 9, 11] ✓
Let's verify with an edge case where low is even:
If low = 6
and high = 11
:
(11 + 1) >> 1 = 12 >> 1 = 6
(odds from 0 to 11: 1, 3, 5, 7, 9, 11)6 >> 1 = 3
(odds from 0 to 5: 1, 3, 5)- Result = 6 - 3 = 3 (odds in range: 7, 9, 11) ✓
The bit shift operation efficiently handles both odd and even boundaries, making this solution both elegant and performant.
Solution Implementation
1class Solution:
2 def countOdds(self, low: int, high: int) -> int:
3 """
4 Count the number of odd integers in the inclusive range [low, high].
5
6 The algorithm works by calculating how many odd numbers exist from 0 up to each bound.
7 - For any integer n, there are (n+1)//2 odd numbers in range [1, n]
8 - Right shift by 1 (>> 1) is equivalent to integer division by 2
9 - (high + 1) >> 1 gives count of odds from 1 to high
10 - low >> 1 gives count of odds from 1 to low-1
11 - The difference gives odds in range [low, high]
12
13 Args:
14 low: The lower bound of the range (inclusive)
15 high: The upper bound of the range (inclusive)
16
17 Returns:
18 The count of odd integers in the range [low, high]
19 """
20 # Calculate number of odd integers from 1 to high
21 odds_up_to_high = (high + 1) >> 1
22
23 # Calculate number of odd integers from 1 to low-1
24 odds_before_low = low >> 1
25
26 # Return the difference to get odds in [low, high]
27 return odds_up_to_high - odds_before_low
28
1class Solution {
2 public int countOdds(int low, int high) {
3 // Count odd numbers in range [low, high] inclusive
4 //
5 // The formula works by counting odd numbers from 0 to high,
6 // then subtracting odd numbers from 0 to (low - 1)
7 //
8 // For any number n:
9 // - If n is even, there are n/2 odd numbers in [1, n]
10 // - If n is odd, there are (n+1)/2 odd numbers in [1, n]
11 //
12 // (high + 1) >> 1 gives us count of odds in [0, high]
13 // low >> 1 gives us count of odds in [0, low - 1]
14
15 int oddsUpToHigh = (high + 1) >> 1; // Right shift by 1 is equivalent to divide by 2
16 int oddsBeforeLow = low >> 1; // Count of odd numbers before low
17
18 return oddsUpToHigh - oddsBeforeLow;
19 }
20}
21
1class Solution {
2public:
3 int countOdds(int low, int high) {
4 // Count odd numbers in range [low, high] using mathematical formula
5 // Right shift by 1 is equivalent to dividing by 2
6
7 // Calculate number of odd integers from 1 to high
8 int oddsUpToHigh = (high + 1) >> 1;
9
10 // Calculate number of odd integers from 1 to (low - 1)
11 int oddsBeforeLow = low >> 1;
12
13 // The difference gives the count of odd numbers in [low, high]
14 return oddsUpToHigh - oddsBeforeLow;
15 }
16};
17
1/**
2 * Counts the number of odd integers in the inclusive range [low, high]
3 *
4 * The algorithm works by calculating how many odd numbers exist from 0 to high,
5 * then subtracting how many odd numbers exist from 0 to low-1.
6 *
7 * For any integer n:
8 * - If n is even, there are n/2 odd numbers in range [1, n]
9 * - If n is odd, there are (n+1)/2 odd numbers in range [1, n]
10 *
11 * Using bit shift right by 1 (>> 1) is equivalent to integer division by 2
12 *
13 * @param low - The lower bound of the range (inclusive)
14 * @param high - The upper bound of the range (inclusive)
15 * @returns The count of odd numbers in the range [low, high]
16 */
17function countOdds(low: number, high: number): number {
18 // Calculate odd numbers from 1 to high (inclusive)
19 const oddsUpToHigh: number = (high + 1) >> 1;
20
21 // Calculate odd numbers from 1 to low-1 (inclusive)
22 const oddsBeforeLow: number = low >> 1;
23
24 // The difference gives us odd numbers in range [low, high]
25 return oddsUpToHigh - oddsBeforeLow;
26}
27
Time and Space Complexity
Time Complexity: O(1)
The solution performs a constant number of operations regardless of the input size. It uses only two bit shift operations (>>
) and one subtraction operation. The bit shift operation n >> 1
is equivalent to integer division by 2 (n // 2
), which is a constant time operation. Therefore, the overall time complexity is constant.
Space Complexity: O(1)
The solution uses only a fixed amount of extra space. It doesn't create any additional data structures or use recursion. Only the input parameters and the result of the arithmetic operations are stored, which requires constant space regardless of the values of low
and high
.
The algorithm cleverly counts odd numbers in the range [low, high]
by using the formula:
(high + 1) >> 1
calculates the count of odd numbers from 0 to highlow >> 1
calculates the count of odd numbers from 0 to low-1- The difference gives the count of odd numbers in the range
[low, high]
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Misunderstanding the Bit Shift Operation
Many developers might incorrectly assume that n >> 1
always gives the count of odd numbers from 0 to n (inclusive). This is actually incorrect:
n >> 1
gives the count of odd numbers from 0 to n-1 when n is oddn >> 1
gives the count of odd numbers from 0 to n when n is even
Incorrect approach:
def countOdds(self, low: int, high: int) -> int:
# WRONG: This misses counting when boundaries are odd
return (high >> 1) - (low >> 1) # Fails for cases like low=3, high=7
Why it fails: When both low and high are odd, this approach doesn't properly include both boundaries in the count.
2. Off-by-One Errors with Boundaries
A common mistake is not handling the inclusive nature of both boundaries correctly:
Incorrect approach:
def countOdds(self, low: int, high: int) -> int:
# WRONG: Subtracts 1 from low unnecessarily
return ((high + 1) >> 1) - ((low - 1) >> 1)
Why it fails: This over-counts because (low - 1) >> 1
gives odd numbers from 0 to low-2, not low-1.
3. Using Complex Conditional Logic Instead of Mathematical Formula
While not incorrect, using multiple if-else conditions makes the solution harder to understand and more error-prone:
Overly complex approach:
def countOdds(self, low: int, high: int) -> int:
count = 0
if low % 2 == 1:
count += 1
low += 1
if high % 2 == 1:
count += 1
high -= 1
count += (high - low) // 2
return count
Why it's problematic: More code means more potential for bugs, and it's less efficient than the bit manipulation approach.
4. Integer Overflow Concerns (in Other Languages)
While Python handles arbitrary precision integers, in languages like Java or C++, adding 1 to high
could cause overflow if high
is at the maximum integer value.
Solution for other languages:
// In Java, handle potential overflow
public int countOdds(int low, int high) {
// Use subtraction to avoid overflow
return (high - low) / 2 + (low % 2 | high % 2);
}
Correct Solution Verification
To avoid these pitfalls, always verify your formula with edge cases:
- Both boundaries odd:
countOdds(3, 7)
should return 3 - Both boundaries even:
countOdds(4, 8)
should return 2 - One odd, one even:
countOdds(3, 8)
should return 3 - Single element ranges:
countOdds(5, 5)
should return 1 (if odd) or 0 (if even)
What is the best way of checking if an element exists in an unsorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
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
Want a Structured Path to Master System Design Too? Don’t Miss This!