Problem overview
The function minAndMax receives a slice of integers, nums, and returns two numbers: the smallest first, the largest second. The slice always has at least one number, and the work must be done in one loop, without a built-in min or max.
For [4, -2, 9, 0] it returns -2 and 9. For [7] both results are 7, and for [-5, -1, -8] they are -8 and -1.
Approach: keep a running smallest and largest
Walk through the slice once and remember the smallest and the largest number seen so far. Each new number is compared with both. If it is below the smallest, it becomes the new smallest. If it is above the largest, it becomes the new largest. When the loop ends, the two variables hold the answer for the whole slice.
The starting values matter. Starting both at 0 is a trap: for [5, 8, 6] that version returns 0 and 8, because 0 is smaller than every number and never gets replaced. Starting both at nums[0] is always safe, because the first number is a real candidate for both roles. This is also why the lesson promises at least one number: nums[0] on an empty slice panics.
Step by step
- Declare
lowandhighwith:=, both set tonums[0]. - Loop over the slice with
for _, num := range nums. The underscore throws away the index, which Go would otherwise reject as an unused variable. - Lower the minimum: if
num < low, assignlow = num. - Raise the maximum: in a separate
if, not anelse, checknum > high. Both checks run for every number, and with a single-element slice neither fires. - Return both after the loop.
On [4, -2, 9, 0] the two variables start at 4. The number 4 changes nothing, -2 lowers low, 9 raises high, and 0 changes nothing, so the loop ends with low = -2 and high = 9. The loop's first pass compares nums[0] with itself, which is harmless.
The solution in Go
func minAndMax(nums []int) (int, int) {
low := nums[0]
high := nums[0]
for _, num := range nums {
if num < low {
low = num
}
if num > high {
high = num
}
}
return low, high
}
Go functions can return several values. The (int, int) after the parameters declares two results, and return low, high sends them back in that order. A caller takes both with lo, hi := minAndMax(nums). For the first example, lo is -2 and hi is 9. Printing the call directly with fmt.Println(minAndMax(nums)) also works and shows -2 9.
There is no tuple type in Go: the two results are separate values, not one pair you can store in a variable.
Testing
Running the function on the statement's examples prints:
[4 -2 9 0] -2 9
[7] 7 7
[-5 -1 -8] -8 -1
Edge cases and common mistakes
- Starting at 0. Wrong when every number is positive or every number is negative, as shown above.
- Treating the two checks as exclusive. A number can only be a new minimum or a new maximum at one time, so
else ifwould work here, but two independentifs are simpler to read and always correct. With one element, neither check fires and both results stay equal to it. - Swapping the results. The smallest comes first. Returning
high, lowfails every test. - Using
:=on a name that already exists in the same scope.low := ...twice in one block is a compile error; assign with=afterwards.
