Problem overview
The method oddEven receives an array of integers, numbers, and returns true when 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 values (1, 3, 5, 7, 9) and four even ones (2, 4, 6, 8). Five is more than four, so the answer is true.
A tie returns false, since "more than" is strict.
Approach: two counters
Go through the array once, deciding for each number whether it is odd or even, and add one to the matching counter. At the end, compare the counters. This needs no extra array and no sorting.
The decision rests on the remainder operator %. A number is even when dividing it by 2 leaves nothing, so number % 2 == 0. Everything else is odd.
Trace the example. Starting with both counters at 0, the numbers 1, 2, 3, 4, 5, 6, 7, 8, 9 alternate odd, even, odd and so on. After the loop oddNumbers is 5 and evenNumbers is 4. The final comparison 5 > 4 is true.
The loop doesn't need both counters to decide the answer. It would be enough to keep one signed tally, adding 1 for an odd number and subtracting 1 for an even one, and return whether it ends above 0. Two named counters are easier to read and to debug, and that is what the lesson uses.
Step by step
- Declare two counters.
oddNumbersandevenNumbers, bothvarand both starting at 0. - Loop over the numbers.
for number in numbersgives each element in turn. - Count the odd ones. Test
number % 2 != 0and add 1 tooddNumbers. - Count the even ones. In the
elsebranch, add 1 toevenNumbers. - Compare. After the loop, return
oddNumbers > evenNumbers. The comparison is already aBool.
The solution in Swift
class Solution {
func oddEven(_ numbers: [Int]) -> Bool {
var oddNumbers = 0
var evenNumbers = 0
for number in numbers {
if number % 2 != 0 {
oddNumbers += 1
} else {
evenNumbers += 1
}
}
return oddNumbers > evenNumbers
}
}
Swift details worth knowing:
- The remainder keeps the sign of the left side. In Swift,
-3 % 2is-1, not 1, and-4 % 2is0. That is why the odd test is!= 0. A test written asnumber % 2 == 1misses every negative odd number. %is the remainder, not a modulo. Swift's operator works with integer division that truncates toward zero, so the result takes the sign of the dividend.- Counters need
var. Withlet,oddNumbers += 1doesn't compile. The typeIntis inferred from the literal 0. - No
++. Swift has no increment operator, so the code uses+= 1. - Returning a comparison. An expression such as
a > bis aBool, soif a > b { return true } else { return false }can be shortened toreturn a > b.
Other ways to test for evenness
Integers have a method for this: number.isMultiple(of: 2) is true for even numbers, including 0 and negative ones. For -3 it is false, and for 4 and 0 it is true. It states the intent directly and avoids the sign question altogether. A bitwise test, number & 1, also works for negative values: it gives 1 for -3 and 0 for -4. For the lesson, the remainder operator is the tool the steps ask for, and it is worth learning how its sign behaves.
Complexity
Time: O(n) for n numbers. Each one costs a single remainder and one addition.
Space: O(1). Two counters and a loop variable are all the function keeps.
Because the check is on the remainder, the size of a number never matters, only its parity. Very large values behave like small ones, and no arithmetic here can overflow.
Edge cases and common mistakes
- Negative numbers.
[-3, -5, 2]has two odd values and one even, so the answer istrue. A test of% 2 == 1would count both -3 and -5 as even and returnfalse. - Zero. 0 is even, because
0 % 2is 0, so it goes to theelsebranch and counts towardevenNumbers. - A tie.
[1, 2]returnsfalse. - Empty array. Both counters stay at 0, which is a tie, so the result is
false. - Declaring the counters inside the loop. They would be reset on every pass and the final comparison would only see the last number: the declarations belong above the loop, where they live for the whole function.
- Forgetting the
else. Without it, the second counter would need its own condition. With it, each number lands in exactly one counter, so the two counts always add up to the length of the array. - Comparing the wrong way round.
evenNumbers > oddNumbersanswers the opposite question.
Testing
Work each case out by hand first, then run it in the editor above. Cases with negative numbers and with ties catch the two most common slips.
[1, 2, 3, 4, 5, 6, 7, 8, 9]givestrue.[-3, -5, 2]givestrue.[1, 2]givesfalse.[]givesfalse.
