Problem overview
The method oddEven receives an array of numbers and returns true if the array has more odd numbers than even numbers, and false otherwise. 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. A tie is not "more", so it returns false.
Approach: two counters and a comparison
The method has to know two numbers, how many odd and how many even, so it keeps two counters. One pass over the array decides, for each element, which counter to increase. When the pass ends, a single comparison of the counters gives the answer.
A number is even when dividing it by 2 leaves a remainder of 0, and odd otherwise. Every number is one or the other, so each element increments exactly one counter, and an if with an else is enough.
Step by step
- Declare both counters in one statement.
let oddNumbers = 0, evenNumbers = 0;creates two variables, each with its own starting value. They useletbecause the loop changes them, and TypeScript infersnumberfrom the zeros. - Loop with
for...of. The loop variablenumberis declared withconst: each pass gets a fresh variable, and the loop body never reassigns it. - Test for odd. The condition is
number % 2 !== 0, and a true result incrementsoddNumbers. - Handle the rest with
else. When the remainder is 0, the number is even andevenNumbersgoes up. Theelseruns exactly when theifcondition is false. - Return the comparison.
oddNumbers > evenNumbersis already aboolean, so the method returns it directly.
The solution in TypeScript
class Solution {
oddEven(numbers: number[]): boolean {
let oddNumbers = 0, evenNumbers = 0;
for (const number of numbers) {
if (number % 2 !== 0) {
oddNumbers++;
} else {
evenNumbers++;
}
}
return oddNumbers > evenNumbers;
}
}
The TypeScript details to know:
- The remainder keeps the sign of the left operand. In TypeScript
3 % 2is1, but-3 % 2is-1. This is why the solution tests!== 0. A test written asnumber % 2 === 1would treat-3as even. -4 % 2is-0. Negative zero is a real value in JavaScript numbers, but it is equal to 0 under===and!==, so negative even numbers are still counted as even.!==is the strict form of!=. It doesn't convert types before comparing.- A parameter and a variable can both be called
number.numberis the name of a type, but it is also usable as a variable name, because types and values live in separate worlds. Using the plural parameternumbersand the singular loop variablenumberis easy to read. - Other ways to test oddness.
Math.abs(number) % 2 === 1works too, because the absolute value removes the sign before the remainder is taken. The lesson's!== 0test is shorter and needs no extra call, and it states the rule plainly: a number is odd when dividing by 2 leaves anything other than zero. - Annotations are erased.
numbers: number[]and: booleandon't exist in the compiled JavaScript.
A trace of the loop
Follow the counters on [4, -7, 10, 3]. Both start at 0.
4 % 2is 0, soevenNumbersbecomes 1.-7 % 2is-1, which differs from 0, sooddNumbersbecomes 1.10 % 2is 0, soevenNumbersbecomes 2.3 % 2is 1, sooddNumbersbecomes 2.
The loop ends with 2 odd and 2 even, and 2 > 2 is false, so the method returns false. If you only need the final comparison, one counter would do: add 1 for each odd number and subtract 1 for each even one, then return whether the balance is above 0. Two counters are easier to read and match the wording of the problem.
Complexity
Time: O(n), where n is the length of the array. The loop does one remainder operation and one increment per element.
Space: O(1). Two counters and the loop variable.
Edge cases and common mistakes
- Negative numbers.
[-3, -1, 2]has two odd values and one even, so the answer istrue. With the=== 1test, both negatives would be counted as even and the method would returnfalse. - All even or all odd. An array of only odd numbers, such as
[1, 3], returnstrue, since two is more than zero. Only even numbers givefalse. - A tie.
[1, 2]has one odd and one even, so the answer isfalse. The comparison must be>, not>=. - An empty array. Both counters stay at 0, and
0 > 0isfalse. - Zero counts as even.
0 % 2is 0, so it incrementsevenNumbers. - Non-integers. The task is about integers. A value such as
3.5gives3.5 % 2 === 1.5, which is not 0, so this code would count it as odd. Don't feed it fractions. - Returning inside the loop. It would judge the array by its first element.
Testing
[1, 2, 3, 4, 5, 6, 7, 8, 9]givestrue.[-3, -1, 2]givestrue.[1, 2]givesfalse.[2, 4, 6]givesfalse.[]givesfalse.