Problem overview
MaxInArray(int[] nums) returns the largest value in nums. For [2, 7, 11, 8, 11, 8, 3, 11] the answer is 11. A value that appears more than once, like 11 here, is still just one answer.
The lesson wants you to write the search yourself with a loop, rather than reach for a built-in that scans the whole array for you.
Approach: keep the best value seen so far
You can't know the maximum until you have seen every element, but you can keep a running champion. Start by treating the first element as the largest. Then look at each element in turn: if it beats the champion, it becomes the new champion. When the loop ends, nobody has beaten the champion, so it is the maximum.
For the example, the champion changes like this as the loop passes each value:
value: 2 7 11 8 11 8 3 11
champion: 2 7 11 11 11 11 11 11
Step by step
- Start
maxValatnums[0]. It is tempting to start at 0, but that is wrong when every number is negative: for[-5, -2, -9]the starting 0 would beat all of them and be returned, even though it isn't in the array. The first element is always a legitimate candidate. - Loop with
foreach.foreach (int val in nums)gives each value in order. The first pass comparesnums[0]with itself, which is harmless. - Update the champion.
maxVal = Math.Max(maxVal, val)keeps the larger of the two.Math.Max(a, b)returns whichever argument is bigger, and it is the same as writingif (val > maxVal) { maxVal = val; }. - Return
maxValafter the loop, when every element has had its chance.
The solution in C#
class Solution {
public int MaxInArray(int[] nums) {
int maxVal = nums[0];
foreach (int val in nums) {
maxVal = Math.Max(maxVal, val);
}
return maxVal;
}
}
Points specific to C# are listed here:
Math.Maxlives in theSystemnamespace. It is a static method, so you call it on the class:Math.Max(a, b). It has overloads forint,long,doubleand the other numeric types, and theintversion is chosen here because both arguments areint.- The comparison form is equally valid. If you prefer to see the decision,
if (val > maxVal) { maxVal = val; }inside the loop gives the same result, and it extends more easily when you need to remember more than the value. - Indexing starts at 0.
nums[0]is the first element andnums[nums.Length - 1]the last. The array size comes from theLengthproperty. - An empty array throws.
nums[0]on an array with no elements raises anIndexOutOfRangeExceptionat run time. An array has no "first element" to start from, and there is also no sensible maximum of nothing.
Complexity
Time: O(n). Each of the n elements is compared once. The maximum of an unsorted array can't be known without looking at every element, so a linear scan is the best you can do.
Space: O(1). The method keeps maxVal and the loop variable.
Edge cases and common mistakes
- All negative numbers.
[-5, -2, -9]must return-2. Starting fromnums[0]handles it, while starting from 0 doesn't. - A single element. The champion is that element and nothing can beat it, so the method returns it.
- Duplicates of the maximum. They don't matter, because the champion is replaced only by a larger value, and an equal one changes nothing.
- Returning inside the loop. The method would stop after the first element and return it.
- Starting from a made-up number. Starting from
int.MinValuealso works, since nothing is smaller, butnums[0]is simpler and works for every numeric type. - Returning the index. The problem asks for the value. Tracking an index is a different lesson.
Testing
[2, 7, 11, 8, 11, 8, 3, 11]gives11.[-5, -2, -9]gives-2.[4]gives4.[3, 3, 3]gives3.[1, 2, 3, 4, 5]gives5, with the maximum at the end.