Problem overview
The method maxInArray receives an array of integers, nums, and returns the largest one. For [2, 7, 11, 8, 11, 8, 3, 11] the answer is 11. The value 11 appears three times, but the method returns it once, as a value.
The statement tells you not to use a built-in such as Math.max() on the whole array, so the loop is yours to write. The reference solution does call Math.max, but only to compare two numbers inside the loop.
Approach: remember the best value so far
Imagine reading the numbers one at a time and keeping a note of the biggest one you've seen. Each new number is compared with the note. If the new number is bigger, the note changes. After the last number, the note holds the maximum.
In code, the note is a variable, maxVal. The only decision is its starting value. Starting at 0 looks natural but is wrong: for [-5, -2, -9] every element is below 0, so the variable would keep 0, a number that isn't even in the array. The safe start is the first element, nums[0]. Whatever the array holds, the first element is a real candidate for the maximum.
Step by step
- Declare
maxValwithlet, typed asnumber, and set it tonums[0]. The variable changes during the loop, so it can't beconst. - Loop over
numswithfor...of. The loop variablevalholds one element per pass. Its first value is the first element again, which is harmless: comparing a number with itself changes nothing. - Keep the larger value. The line
maxVal = Math.max(maxVal, val)assigns the larger of the two numbers tomaxVal. After every pass,maxValis the largest value seen so far. - Return
maxValafter the loop, once every element has been considered.
The solution in TypeScript
class Solution {
maxInArray(nums: number[]): number {
let maxVal: number = nums[0];
for (let val of nums) {
maxVal = Math.max(maxVal, val);
}
return maxVal;
}
}
Some TypeScript details:
Math.maxwith two arguments. It returns the larger of its arguments. Here it replaces anif (val > maxVal) { maxVal = val; }and means the same thing.- Indexing returns
number, even when the index is missing. With the compiler settings used here,nums[0]has the typenumber. If the array were empty, the JavaScript would holdundefinedthere, and the annotation would not warn you. That is the reason the empty array deserves a thought, below. - Types vanish at run time.
nums: number[]checks nothing when the program runs. Only the values decide what happens. - The spread trap.
Math.max(...nums)is the shortcut the lesson avoids. Besides defeating the exercise, spreading a very large array into function arguments can fail with a stack error, whereas the loop has no such limit.
Complexity
Time: O(n), where n is the length of nums. Each element is compared once.
Space: O(1). The method keeps maxVal and the loop variable only.
Edge cases and common mistakes
- All negative numbers.
[-5, -2, -9]returns-2becausemaxValstarts at-5. A start at 0 would return 0. - A single element.
[4]returns4; nothing larger ever appears. - Duplicates of the maximum. They make no difference. The maximum is a value, not a position.
- An empty array. There is no maximum. The reference solution starts from
nums[0], which isundefinedfor an empty array, and the method returnsundefinedwithout throwing. The lesson's tests use non-empty arrays. Real code should checknums.lengthfirst and decide what an empty input means. - Starting with a made-up small value. Any fixed constant, such as
-1000, fails when the data contains something smaller. The first element is always safe. - Returning inside the loop, which would stop after the first element.
Testing
[2, 7, 11, 8, 11, 8, 3, 11]gives11.[-5, -2, -9]gives-2.[4]gives4.[3, 9, 1]gives9.