Problem overview
The method minAndMax gets an array of integers, nums, and returns its smallest and largest number together as a tuple [number, number], smallest first. The array has at least one number. The task asks for one loop and no built-in min or max.
For [4, -2, 9, 0] the result is [-2, 9]. For [7] it is [7, 7], since the only number is both the smallest and the largest. For [-5, -1, -8] it is [-8, -1].
Approach
Keep two variables, low and high, that always hold the smallest and largest numbers seen so far. Look at each number once: if it is below low, it becomes the new low; if it is above high, it becomes the new high. After the last number, both variables are final.
Where to start
Both variables start at nums[0]. Starting at 0 would be wrong when every number is above 0 (the low would stay 0) or every number is below 0 (the high would stay 0). The first number is always a real candidate. This also covers the one-number array without extra code.
Step by step
- Declare
lowandhighasnumbers withlet, both set tonums[0]. They needletbecause they change. - Loop over
numswithfor...of. - Inside the loop, compare each
numwithlowand update it whennumis smaller. - Below that, still inside the loop, compare
numwithhighand update it whennumis larger. These are two separateifstatements, not anelse: every number is tested against both bounds,, and a single number can update at most one of them. - After the loop, return
[low, high].
The solution in TypeScript
class Solution {
minAndMax(nums: number[]): [number, number] {
let low: number = nums[0];
let high: number = nums[0];
for (let num of nums) {
if (num < low) {
low = num;
}
if (num > high) {
high = num;
}
}
return [low, high];
}
}
The return type [number, number] is a tuple type: the compiler checks that the returned array has two numbers. The tuple is an ordinary array at run time, so a caller can print it or destructure it with const [smallest, largest] = ....
The first pass looks at nums[0] against itself, which changes nothing. That is harmless.
Why one pass is enough
After each number, low is the smallest of the numbers looked at so far and high is the largest. That stays true when the next number arrives, because the new smallest is either the old low or the new number. When the loop ends, "so far" means the whole array. Finding both values in one loop does half the work of two separate loops, though both are linear: the time grows in step with the array's length, and only two extra variables are used.
Testing
These results come from calling the method on the statement's examples:
| nums | Result |
|---|---|
[4, -2, 9, 0] | [-2, 9] |
[7] | [7, 7] |
[-5, -1, -8] | [-8, -1] |
Common mistakes
- Starting at 0. With
[-5, -1, -8], a high that starts at 0 would end as 0, a number that is not in the array. - Returning
[high, low]. The smallest comes first. - Using the built-ins.
Math.min(...nums)is the short way, and a later lesson uses it, but this exercise asks for one loop.
