Start learning free

LESSON 153 OF 414 · LOOPS & GLOBAL VARIABLES

Odd Even in Rust: Counting with a Loop and the Remainder

Practice Read the full explanation

Given an array, return true if there are more odd numbers than even numbers, otherwise return false.

Example:

Input: numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Output: true

Explanation:
There are 5 odd numbers in the array: 1, 3, 5, 7, 9
There are 4 even numbers in the array: 2, 4, 6, 8
5 is greater than 4, so our function should return true
STEP 1 OF 5
    Ctrl + Enter to check

    RUST · LOOPS & GLOBAL VARIABLES

    Odd Even in Rust, explained

    Problem overview

    The function odd_even receives a vector of integers, numbers, and returns a bool: true if the vector holds more odd numbers than even numbers, and false otherwise. A tie, including an empty vector, gives false.

    For [1, 2, 3, 4, 5, 6, 7, 8, 9] there are five odd numbers (1, 3, 5, 7, 9) and four even ones (2, 4, 6, 8). Five is greater than four, so the answer is true.

    Approach: two counters and one comparison

    You need two numbers: how many odd values there are and how many even ones. Count both in a single pass. Each element is either odd or even, so every iteration increases exactly one of the two counters. After the loop, one comparison gives the answer.

    To classify a number, use the remainder operator %. An even number leaves remainder 0 when divided by 2, and an odd number doesn't.

    Here is the idea on [4, 7, 10, 3, 9]. The counters start at 0 and 0. The value 4 is even, so the counters become 0 and 1. The value 7 is odd (1 and 1), 10 is even (1 and 2), 3 is odd (2 and 2) and 9 is odd (3 and 2). The loop ends with three odd numbers against two even ones, so the function returns true.

    You could also keep a single counter that goes up for an odd number and down for an even one, and return whether it ends above zero. Two counters are easier to read and to debug, and they cost almost nothing, so this lesson uses them.

    Step by step

    1. Declare odd_numbers and even_numbers with let mut, both starting at 0. They need mut because the loop increments them, and without it the compiler rejects +=.
    2. Write a for loop over numbers with the loop variable number. It visits every element in order.
    3. Test for odd. Inside the loop, check number % 2 != 0 and increment odd_numbers in that branch. The check is "not 0" rather than "equal to 1" for a reason covered below.
    4. Add the else branch for even numbers and increment even_numbers there.
    5. Return the comparison. odd_numbers > even_numbers is already a bool, so the function returns it directly instead of wrapping it in an if that returns true or false.

    The solution in Rust

    impl Solution {
        fn odd_even(numbers: Vec<i32>) -> bool {
            let mut odd_numbers = 0;
            let mut even_numbers = 0;
            for number in numbers {
                if number % 2 != 0 {
                    odd_numbers += 1;
                } else {
                    even_numbers += 1;
                }
            }
            return odd_numbers > even_numbers;
        }
    }
    

    The Rust details worth a closer look:

    • The sign of %. In Rust, the result of % takes the sign of the left operand. So 3 % 2 is 1, but -3 % 2 is -1. A test like number % 2 == 1 would count -3 as even. Comparing with != 0 works for both signs. Rust also has rem_euclid, which never returns a negative remainder: (-3i32).rem_euclid(2) is 1.
    • Inferred counter types. The counters start as a bare 0, and Rust picks a type for them. Nothing else constrains them here, so they default to i32. Comparing them with each other is fine because both have the same type.
    • Looping by value. for number in numbers moves the vector into the loop, and each number is an i32 rather than a reference, so no dereferencing is needed. The function owns numbers and doesn't use it afterwards, so moving it is fine.
    • if / else as the only two cases. Because every integer is either odd or even, the else branch needs no condition of its own.

    Complexity

    Let n be the number of elements.

    Time: O(n). One pass over the vector, with a constant amount of work per element.

    Space: O(1). Two counters, whatever the length of the vector.

    Edge cases and common mistakes

    • Negative numbers. [-1, -3, 2] has two odd values and one even, so the answer is true. With the == 1 test, both negative odds would fall into the even count and the answer would be false.
    • Ties. [1, 2] has one of each, so the answer is false. The comparison is strict: "more than", not "at least as many as".
    • Empty vector. Both counters stay 0, 0 is not greater than 0, and the result is false.
    • Zero. 0 is even, since 0 % 2 is 0, so it adds to the even count like any other even number. A vector of only zeros returns false.
    • Extreme values. i32::MAX (2147483647) is odd and i32::MIN (-2147483648) is even. The remainder by 2 gives the right class for both, because the check never adds or multiplies the number, so nothing can overflow.
    • Forgetting mut. The counters can't be incremented without it.
    • Returning inside the loop. The answer is known only after all elements are counted, so the comparison goes after the loop.

    Testing

    • [1, 2, 3, 4, 5, 6, 7, 8, 9] gives true.
    • [-1, -3, 2] gives true.
    • [1, 2] gives false.
    • [] gives false.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free