Facebook Pixel

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 and high = 7, the odd numbers in this range are [3, 5, 7], so the count is 3
  • If low = 8 and high = 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 to n (inclusive)
  • By subtracting the count of odds before low from the count of odds up to high, we get the desired result
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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:

  1. Calculate odd numbers from 0 to high:

    • (high + 1) >> 1 computes the count of odd numbers from 0 to high (inclusive)
    • The right shift by 1 (>> 1) is equivalent to integer division by 2
    • Adding 1 to high before dividing ensures we count correctly when high is odd
  2. Calculate odd numbers from 0 to low-1:

    • low >> 1 computes the count of odd numbers from 0 to low - 1 (inclusive)
    • This gives us the count of odd numbers that come before our range
  3. Subtract to get the final count:

    • The difference between these two values gives us exactly the count of odd numbers in [low, high]

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 if high is odd, it gets counted
  • By using low >> 1, we ensure that if low 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 Evaluator

Example 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 high
  • low >> 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 odd
  • n >> 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)
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

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

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

Load More