Problem overview
The function oddEven receives a slice of integers, numbers, and returns true if the slice contains more odd numbers than even numbers. Otherwise, including when the counts are equal, it returns false.
For [1, 2, 3, 4, 5, 6, 7, 8, 9] there are five odd numbers (1, 3, 5, 7, 9) and four even numbers (2, 4, 6, 8). Five is greater than four, so the answer is true.
Approach
Count the odd numbers and the even numbers in a single pass, then compare the two counts. Every element is either odd or even, so each one increments exactly one of two counters. After the loop, the answer is whether the odd counter is strictly larger.
The test for oddness uses the remainder operator %. An even number leaves remainder 0 when divided by 2, and an odd number leaves a non-zero remainder. Writing the test as "remainder is not 0" is more robust than "remainder is 1", and the reason is specific to Go and several other languages.
Step by step
- Declare two counters.
oddNumbers := 0andevenNumbers := 0each infer the typeintfrom the literal 0. - Loop over the slice with
for ... range, naming the elementnumber. The index is not needed, and Go does not allow unused variables, so it goes to the blank identifier_. - Test for odd. Inside the loop, an
ifchecks thatnumber % 2is not 0. When it is, incrementoddNumbers. - Handle even. An
elsebranch covers the other case. Go requireselseon the same line as the closing brace of theifblock, as in} else {. - Return the comparison.
oddNumbers > evenNumbersis already abool, so it can be returned directly without anif.
The solution in Go
func oddEven(numbers []int) bool {
oddNumbers := 0
evenNumbers := 0
for _, number := range numbers {
if number % 2 != 0 {
oddNumbers += 1
} else {
evenNumbers += 1
}
}
return oddNumbers > evenNumbers
}
The Go details worth knowing:
- The sign of
%. In Go, the result of%takes the sign of the dividend, the number on the left. So7 % 2is 1, but-7 % 2is -1, not 1. A test written asnumber % 2 == 1would classify every negative odd number as even. The testnumber % 2 != 0works for positive and negative numbers alike, because odd numbers leave 1 or -1 and even numbers leave 0. - Counting both sides. Because the final comparison is strict, a tie returns
false. Counting both kinds is needed only because the comparison involves both counts; you could also keep a single balance that goes up for an odd number and down for an even one, and return whether it is positive at the end. += 1or++. Both increment a counter. The lesson uses+= 1;oddNumbers++is the more common Go style. Either is a statement and not an expression.- Returning a comparison. A condition like
a > balready has the typebool, soif a > b { return true }; return falseis just a longer way to writereturn a > b.
Complexity
Time: O(n). One pass over the n elements, with constant work for each.
Space: O(1). Only the two counters and the loop variable are stored.
Edge cases and common mistakes
- Negative odd numbers. For
[-1, -3, 2], the answer istrue: two odd numbers against one even. Testingnumber % 2 == 1would count -1 and -3 as even and wrongly returnfalse. - Zero. 0 is even, and
0 % 2is 0, so it is counted as even. - A tie.
[1, 2]has one of each, and the result isfalse. Using>=would be a bug. - An empty or
nilslice. Both counters stay 0, and0 > 0isfalse. - Putting
elseon a new line. A line that begins withelseis a syntax error in Go.
Testing
[]int{1, 2, 3, 4, 5, 6, 7, 8, 9}givestrue.[]int{-1, -3, 2}givestrue.[]int{1, 2}givesfalse.[]int{}givesfalse.