Problem overview
The method hasPassed receives an array of numbers, grades, and returns true if the average grade is 5 or more, and false otherwise. The average is the sum of the grades divided by how many there are.
In the first example, [4, 7, 5, 9, 8, 2] sums to 35. Divided by 6 grades that is about 5.83, which is at least 5, so the answer is true. In the second example, [4, 7, 5, 3, 8, 2] sums to 29, and 29 / 6 is about 4.83. That is below 5, so the answer is false.
Approach: sum, divide, compare
The problem splits into three small jobs, done in order:
- add up all the grades;
- divide the sum by the number of grades to get the average;
- compare the average with 5.
Only the first job needs a loop. A running total starts at 0, and each grade is added to it as the loop visits that grade. The other two jobs are one line each. The loop visits every grade once, so the time is proportional to the number of grades, and only a few variables are stored.
Step by step
- Declare
sumwithletand set it to 0. It is the running total, and since the loop updates it, it can't beconst. - Loop over the grades with
for...of. The loop variablegradeis declared withconstand holds one array element per pass. The loop doesn't need the positions of the elements, only their values, sofor...ofis simpler than counting indices. - Add
gradetosumon each pass. After the loop,sumholds the total of all grades. - Compute the average. Declare
averageassum / grades.length. Dividing twonumbervalues in TypeScript keeps the fractional part, so 35 / 6 is 5.833..., not 5. - Return the comparison.
average >= 5is already aboolean, so the method returns it directly. Anifthat returnstruein one branch andfalsein the other would only repeat what the expression says.
The solution in TypeScript
class Solution {
hasPassed(grades: number[]): boolean {
let sum: number = 0;
for (const grade of grades) {
sum += grade;
}
let average: number = sum / grades.length;
return average >= 5;
}
}
The TypeScript points worth noting:
- Division does not truncate. Every number is a double, so
7 / 2is3.5. Some other languages give 3 for the same expression with integers, but not TypeScript. If you wanted a whole-number result, you'd have to ask for it withMath.floororMath.trunc. For this lesson the fractional part is not needed to decide the answer, but it keeps the average meaningful. grades.lengthis a property. There are no parentheses afterlength.- The annotations check nothing at run time.
grades: number[]tells the compiler what to expect, but it is erased in the JavaScript. The compiler reports a call such ashasPassed(["5"]), yet the JavaScript would still run. - One expression is enough for the return.
return average >= 5;works because a comparison producestrueorfalse.
Complexity
Time: O(n), where n is the number of grades. The loop does one addition per grade, and the division and comparison happen once.
Space: O(1). The method stores sum, average and the loop variable, whatever the size of the array.
Edge cases and common mistakes
- The average is exactly 5. The condition is "5 or more", so
>=is needed. For[5, 5, 5, 4, 6]the sum is 25, the average is 5, and the answer istrue. Writing>would returnfalse. - A single grade.
[5]has an average of 5 and returnstrue. - An empty array. The sum is 0 and the length is 0, and in TypeScript
0 / 0isNaN, not an error. Every comparison withNaNis false, so the method returnsfalse. The lesson does not ask about this case, but it is worth knowing that no exception is thrown. - Dividing by the wrong number. The divisor is the number of grades,
grades.length, and not the largest index or a fixed number such as 10. - Comparing the sum.
sum >= 5would pass nearly every class. The comparison is on the average.
Testing
[4, 7, 5, 9, 8, 2]givestrue.[4, 7, 5, 3, 8, 2]givesfalse.[5, 5, 5, 4, 6]givestrue(the average is exactly 5).[5]givestrue.[]givesfalse.