Problem overview
The function maxInArray receives a slice of integers, nums, and returns the largest value in it. For [2, 7, 11, 8, 11, 8, 3, 11] the answer is 11. The value 11 appears three times, which doesn't matter: the function returns the value, not a position or a count.
Approach
Keep a variable that holds the largest value seen so far, and look at every element once. Whenever an element is larger than the stored one, replace it. After the last element, the variable holds the maximum of the whole slice.
The choice of starting value matters. The tempting start is 0, but it fails when every number is negative: for [-5, -2, -9], a start of 0 is larger than all of them and the function would return 0, a number that isn't in the slice. Starting with the first element avoids this, because the answer is always an element of the slice and the first element is a valid candidate to begin with.
Step by step
- Initialize
maxValwithnums[0]using:=. It becomes anintholding the first element. - Loop over the values.
for _, num := range numsgives each element in turn asnum. The blank identifier_discards the index, since Go does not allow unused variables. - Update the maximum. Inside the loop, set
maxValto the larger ofmaxValandnum. Go provides a built-inmaxfunction for this, so the assignment is a single line, andmaxValalways holds the largest value seen so far. - Return
maxValafter the loop.
The solution in Go
func maxInArray(nums []int) int {
maxVal := nums[0]
for _, num := range nums {
maxVal = max(maxVal, num)
}
return maxVal
}
The Go details worth knowing:
- The built-in
max. Go 1.21 added the built-insminandmax. They accept two or more arguments of the same ordered type, somax(3, 8)is 8. Before that version, Go had no such function in the standard language and people wrote the comparison themselves. - The same thing without the built-in. If you prefer to spell it out, replace the assignment with an
if:
It gives the same result for every input. Forif num > maxVal { maxVal = num }[2, 7, 11, 8, 11, 8, 3, 11]it returns 11, and for[-5, -2, -9]it returns -2. - The first element is compared with itself. The loop starts at index 0, so the first pass compares
nums[0]withnums[0]. This is harmless. A loop that starts at index 1 would skip the useless comparison, but it needs the index and a three-partfor, and the saving is negligible. - No ternary operator. Go has no
a > b ? a : b, which is one reason the built-inmaxand the plainifare the two ways to write this.
Complexity
Time: O(n). The loop looks at each of the n elements once, and each comparison takes constant time. Any correct solution has to read every element, because the largest one could be anywhere.
Space: O(1). The function stores only maxVal and the loop variable.
Edge cases and common mistakes
- All negative numbers.
[-5, -2, -9]returns -2. StartingmaxValat 0 would return 0 instead. - A single element.
[42]returns 42. - An empty slice.
nums[0]does not exist, so the function stops the program with a run-time panic,index out of range [0] with length 0. This solution assumes at least one element. If empty input were possible, checklen(nums) == 0first and decide what to return. - Duplicated maxima.
[11, 7, 11]returns 11. Nothing special is needed. - Returning inside the loop. The function would give up after the first element.
- Using a tiny constant as the start. Starting from a fixed number such as -1000 works only while the data stays above it. The first element works for every input.
Testing
[]int{2, 7, 11, 8, 11, 8, 3, 11}gives11.[]int{-5, -2, -9}gives-2.[]int{42}gives42.[]int{1, 2, 3}gives3.