Problem overview
The function minAndMax receives an array of integers, nums, which always has at least one number. It returns the smallest and the largest number together, as a tuple (low: Int, high: Int) with the smallest first. The statement asks for a single loop and no built-in min or max.
For [4, -2, 9, 0] the result is (low: -2, high: 9). For [7] it is (low: 7, high: 7), because one number is both the smallest and the largest.
Approach
Keep two variables, low and high, the smallest and the largest number seen so far. Look at each number once. If it is smaller than low, it becomes the new low. If it is larger than high, it becomes the new high. When the loop ends, both variables hold the answer.
The starting values matter. Starting both at 0 is wrong when every number is above 0 (the true smallest would never replace 0) or every number is below 0. The first number is always a real candidate, so both variables start at nums[0]. That is safe because the array is never empty.
Here is the loop on [4, -2, 9, 0]. Both variables start at 4. The table shows low and high after each number is handled.
| num | low | high |
|---|---|---|
| 4 | 4 | 4 |
| -2 | -2 | 4 |
| 9 | -2 | 9 |
| 0 | -2 | 9 |
A single pass is enough because each number only has to be compared with the two values already kept. Nothing needs to be sorted or remembered beyond those two.
Step by step
- Declare
lowandhighwithvar, both set tonums[0]. They change inside the loop, soletwon't do. - Loop over
numswithfor num in nums. One pass checks each number against both variables. - Update
lowwhennum < low. - Update
highwhennum > high. This is a secondif, not anelse: the two tests are independent, and each number is checked against both. - Return
(low, high)after the loop.
The solution in Swift
class Solution {
func minAndMax(_ nums: [Int]) -> (low: Int, high: Int) {
var low = nums[0]
var high = nums[0]
for num in nums {
if num < low {
low = num
}
if num > high {
high = num
}
}
return (low, high)
}
}
Two Swift details:
- The return type supplies the labels.
return (low, high)has no labels of its own, but the declared type(low: Int, high: Int)gives them, so the caller can writeresult.lowandresult.high. For[4, -2, 9, 0],result.lowis -2 andresult.highis 9. nums[0]traps on an empty array. Swift stops the program with an index-out-of-range error instead of returning garbage. The constraints rule out an empty array, so no check is needed here.
Edge cases and common mistakes
- One number.
[7]gives(low: 7, high: 7). - All negative numbers.
[-5, -1, -8]gives(low: -8, high: -1). Ahighthat started at 0 would wrongly stay 0. - All positive numbers.
[3, 8, 5]gives(low: 3, high: 8). Alowthat started at 0 would wrongly stay 0. - Swapped return values. The smallest comes first, so
(high, low)returns the pair in the wrong order for any array with two different values. - Putting both updates in one branch. If the assignment to
highsits inside theif num < lowblock,highis updated only for numbers that are new minimums, and[3, 8, 5]returns(low: 3, high: 3). - Built-ins. Swift arrays have
min()andmax()methods, which this lesson leaves out so that you practise the loop they hide.
Testing
[4, -2, 9, 0]gives(low: -2, high: 9).[7]gives(low: 7, high: 7).[-5, -1, -8]gives(low: -8, high: -1).[3, 8, 5]gives(low: 3, high: 8).
