Problem overview
The function oddEven receives an IntArray named numbers and returns a Boolean: true when the array holds more odd numbers than even numbers, and false otherwise. A tie counts as false.
In the example, [1, 2, 3, 4, 5, 6, 7, 8, 9] has five odd numbers (1, 3, 5, 7, 9) and four even numbers (2, 4, 6, 8). Five is more than four, so the answer is true.
Approach: two counters and a comparison
The question compares two quantities, so count both. Walk through the array once. For each number, decide whether it is odd or even and increase the matching counter. At the end, compare the counters.
The test for oddness uses the remainder operator %. An even number leaves remainder 0 when divided by 2, and an odd number does not. Each number is odd or even, so a plain if with an else covers every case.
Trace [2, 4, 1] to see the counters move. Both start at 0. The number 2 leaves remainder 0, so evenNumbers becomes 1. The number 4 does the same, making it 2. The number 1 leaves remainder 1, so oddNumbers becomes 1. At the end, 1 is not greater than 2, and the function returns false.
Only the relative size of the two counts matters, so the actual totals can be large or small. The array length is not needed, and neither is a division to find a percentage.
Step by step
- Declare two counters,
oddNumbersandevenNumbers, both starting at 0. They arevars because the loop changes them, and Kotlin infers the typeIntfrom the literal 0. - Loop over the array with
for (number in numbers), which visits each element in order. - Count the odd ones. Inside the loop, an
ifchecksnumber % 2 != 0and runsoddNumbers++when it is true. The check is "not 0", not "equal to 1", for a reason explained below. - Count the even ones. The
elsebranch runs exactly when the condition is false, that is, when the remainder is 0, and incrementsevenNumbers. - Return the comparison
oddNumbers > evenNumbers. It is already aBoolean, so no extraifis needed.
The solution in Kotlin
class Solution {
fun oddEven(numbers: IntArray): Boolean {
var oddNumbers = 0
var evenNumbers = 0
for (number in numbers) {
if (number % 2 != 0) {
oddNumbers++
} else {
evenNumbers++
}
}
return oddNumbers > evenNumbers
}
}
The Kotlin details behind it:
- The remainder keeps the sign of the left operand.
7 % 2is 1, but-3 % 2is -1, not 1. A test written asnumber % 2 == 1would treat -3 as not odd and count it as even. Comparing with 0 works for positive and negative numbers alike, because every even number gives exactly 0, and-4 % 2is 0. - Division and remainder go together. Integer division truncates toward zero, and
%is the matching remainder, which is why the sign follows the dividend. If you ever need a result that is never negative,Math.floorMod(-3, 2)gives 1. - Other ways to test parity. Kotlin also has
number % 2 == 0for evenness, which gives the same split with the branches swapped, andnumber and 1, which reads the lowest bit and is 1 for every odd number, negative ones included. The remainder test is the clearest for beginners, so the lesson uses it. Whichever test you pick, compare against 0 when you use%. - Comparison results are values.
oddNumbers > evenNumbersis aBooleanexpression. Writingif (oddNumbers > evenNumbers) { return true } else { return false }would do the same thing in more lines. ++on avar.oddNumbers++adds 1 to the variable. It works only on avar, not on aval.
Complexity
Let n be the length of numbers.
Time: O(n). Each element gets one remainder check and one increment.
Space: O(1). The function stores two counters and the loop variable.
You could also keep a single counter, adding 1 for an odd number and subtracting 1 for an even one, and then test whether it ends above 0. The two-counter version is easier to read.
Edge cases and common mistakes
- A tie.
[1, 2]has one odd and one even number, so the function returnsfalse. That is why the comparison is strictly greater. - An empty array. Both counters stay 0, and 0 is not greater than 0, so the result is
false. - Negative numbers.
[-3, -5, 2]has two odd numbers and one even number, so the result istrue. This is where% 2 == 1goes wrong. - Large arrays. The counters are
Intvalues, so they hold any array length Kotlin can create. They can never overflow. - Zero. Zero is even.
0 % 2is 0, so it lands in theelsebranch. - Returning inside the loop. The function would decide on the first element.
- Using
>=. It would returntruefor ties.
Testing
[1, 2, 3, 4, 5, 6, 7, 8, 9]givestrue.[1, 2]givesfalse.[-3, -5, 2]givestrue.[2, 4, 1]givesfalse.[]givesfalse.