{x}
blog image

Highest Grade For Each Student

Solution Explanation for LeetCode Problem 1112: Highest Grade For Each Student

This problem requires finding the highest grade achieved by each student and the corresponding course ID. In case of ties in the highest grade, the course with the lowest course_id should be selected. The result should be ordered by student_id.

Two approaches are presented below, both using SQL:

Solution 1: Using RANK() Window Function

This solution leverages the power of window functions for efficient ranking and filtering.

Approach:

  1. Window Function: A Common Table Expression (CTE) called T is created. Inside, the RANK() window function is applied. RANK() assigns a rank to each row within a partition (each student's records). The partitioning is done by student_id, and the ordering is first by grade in descending order (highest grade first) and then by course_id in ascending order (lowest course ID in case of tie).

  2. Filtering: The main query selects student_id, course_id, and grade from T, filtering only the rows where the rank (rk) is 1. This ensures we get only the top record for each student (highest grade, lowest course_id in case of tie).

  3. Ordering: Finally, the result is ordered by student_id in ascending order as required.

MySQL Code:

WITH
    T AS (
        SELECT
            *,
            RANK() OVER (
                PARTITION BY student_id
                ORDER BY grade DESC, course_id
            ) AS rk
        FROM Enrollments
    )
SELECT student_id, course_id, grade
FROM T
WHERE rk = 1
ORDER BY student_id;

Time Complexity: O(N log N), where N is the number of rows in the Enrollments table. This is due to the sorting involved in the RANK() function. The exact complexity depends on the database engine's implementation of window functions.

Space Complexity: O(N) in the worst case, due to the intermediate CTE T potentially storing all rows. Again, the actual space usage depends on the database engine's optimization strategies.

Solution 2: Using Subqueries

This solution uses nested subqueries to achieve the same result.

Approach:

  1. Inner Subquery: The inner subquery finds the maximum grade for each student using MAX(grade) and GROUP BY student_id.

  2. Outer Query: The outer query joins the Enrollments table with the result of the inner subquery. It selects rows where the (student_id, grade) combination matches the highest grade for each student. The MIN(course_id) is used to select the course with the lowest ID in case of multiple courses with the highest grade.

  3. Grouping and Ordering: The outer query then groups the results by student_id and orders them by student_id.

MySQL Code:

SELECT student_id, MIN(course_id) AS course_id, grade
FROM Enrollments
WHERE
    (student_id, grade) IN (
        SELECT student_id, MAX(grade) AS grade
        FROM Enrollments
        GROUP BY 1
    )
GROUP BY 1
ORDER BY 1;

Time Complexity: This approach also has a time complexity of O(N log N) due to the sorting implicit in the GROUP BY and MAX() operations within the subqueries. The exact complexity depends on the database engine's optimization of these operations.

Space Complexity: O(N) in the worst case, as the intermediate results from subqueries could potentially store all rows. This depends again on the database optimizer.

Comparison:

Both solutions achieve the same result. The RANK() window function approach might be considered slightly more readable and potentially more efficient in some database systems, especially for very large datasets, as it avoids the join operation used in the subquery method. However, the performance difference may be minimal in practice and depends on the specific database engine and its optimizations. The choice depends on personal preference and familiarity with SQL features.