Start learning free

LESSON 264 OF 671 · SORTING & BUILT-INS

Min and Max in Go: Two Values in One Loop

Practice Read the full explanation

You get a slice of integers nums. Return its smallest and its largest number together, as a pair.

The smallest number comes first. The function's return type shows how your language holds the pair.

Find both in one loop. Don't use a built-in min or max function.

 

Example 1:

Input: nums = [4, -2, 9, 0]
Output: (-2, 9)
Explanation: The smallest number is -2.
The largest number is 9.

Example 2:

Input: nums = [7]
Output: (7, 7)
Explanation: The only number is both the smallest and the largest.

Example 3:

Input: nums = [-5, -1, -8]
Output: (-8, -1)
Explanation: All the numbers are below 0.
The smallest is -8, and the largest is -1.

 

Constraints:

  • nums has at least one number.
  • Every number is between -106 and 106.
STEP 1 OF 5
    Ctrl + Enter to check

    GO · SORTING & BUILT-INS

    Min And Max in Go, explained

    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

    1. Declare low and high with :=, both set to nums[0].
    2. Loop over the slice with for _, num := range nums. The underscore throws away the index, which Go would otherwise reject as an unused variable.
    3. Lower the minimum: if num < low, assign low = num.
    4. Raise the maximum: in a separate if, not an else, check num > high. Both checks run for every number, and with a single-element slice neither fires.
    5. 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 if would work here, but two independent ifs 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, low fails 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.
    Keep going with Go500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free