2545. Sort the Students by Their Kth Score
Problem Description
You have a classroom with m
students and n
exams. Each student has taken all n
exams and received scores for each one.
You're given a 2D matrix called score
where:
- Each row represents one student
- Each column represents one exam
score[i][j]
is the score that studenti
got on examj
- All scores in the matrix are distinct (no two scores are the same)
Your task is to sort the students based on their performance in a specific exam. Given an integer k
, you need to:
- Look at the scores from the
k
-th exam (columnk
) - Sort all students (rows) based on these scores
- Arrange students from highest score to lowest score in that exam
The solution uses Python's built-in sorted()
function with a custom key. The key lambda x: -x[k]
extracts the score from column k
for each row x
, and the negative sign ensures descending order sorting. This efficiently reorders all rows of the matrix based on the values in the specified column.
For example, if k = 1
and you have scores for 3 students and 2 exams, the students would be reordered so that whoever scored highest on exam 1 appears first, then the second-highest scorer, and so on.
Intuition
The problem essentially asks us to rearrange rows of a matrix based on values in a specific column. This is a classic sorting problem with a twist - instead of sorting a single array, we're sorting entire rows while using one particular column as the sorting criterion.
When we need to sort students by their scores in the k
-th exam, we're really just sorting the rows of the matrix based on the values at index k
in each row. Think of it like sorting a list of people by their age - you look at one specific attribute (age) to determine the order, but you move the entire person record when reordering.
The key insight is that Python's sorted()
function can handle this elegantly. We can pass the entire matrix and specify a custom sorting key that extracts just the value we care about from each row. Since we want descending order (highest scores first), we can either:
- Use
sorted()
withreverse=True
- Negate the value in our key function (turning large positive values into large negative values)
The second approach with -x[k]
is more concise. When Python sorts by negative values, what was originally the largest positive value becomes the smallest negative value and appears first in the sorted result. For instance, if exam scores are [85, 92, 78]
, negating gives [-85, -92, -78]
, and sorting these in ascending order gives [-92, -85, -78]
, which corresponds to the original values [92, 85, 78]
- exactly the descending order we want.
This approach works because we're guaranteed all scores are distinct, so there are no ties to worry about. Each row will have a unique position in the final sorted order based on its score in column k
.
Learn more about Sorting patterns.
Solution Approach
The solution uses Python's built-in sorted()
function to rearrange the rows of the matrix based on scores in the k
-th column.
Implementation Details:
-
Input Parameters:
score
: A 2D list representing the matrix of student scoresk
: The index of the exam column to sort by
-
Sorting Mechanism:
- We call
sorted(score, key=lambda x: -x[k])
- The
sorted()
function creates a new sorted list from the input - Each element being sorted is a row (a list of scores for one student)
- We call
-
Key Function:
lambda x: -x[k]
is an anonymous function that:- Takes a row
x
as input - Accesses the score at position
k
usingx[k]
- Returns the negative of that score
-x[k]
- Takes a row
-
Why Negative Values:
- By default,
sorted()
arranges elements in ascending order - We want descending order (highest scores first)
- Negating the values reverses the order: the highest positive score becomes the lowest negative value
- Example: If column
k
has values[75, 90, 82]
, the key function returns[-75, -90, -82]
- Sorting these gives
[-90, -82, -75]
, which corresponds to rows with original scores[90, 82, 75]
- By default,
-
Time and Space Complexity:
- Time Complexity:
O(m log m)
wherem
is the number of students (rows), as we're sortingm
elements - Space Complexity:
O(m)
for the sorted list that's returned
- Time Complexity:
The beauty of this approach is its simplicity - Python's sorting infrastructure handles all the heavy lifting of maintaining row integrity while reordering based on a single column's values.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's work through a concrete example to understand how the solution works.
Given:
- A classroom with 4 students and 3 exams
- Score matrix:
Exam0 Exam1 Exam2 Student 0: [10, 6, 9] Student 1: [7, 5, 3] Student 2: [8, 11, 2] Student 3: [9, 7, 1]
- We want to sort by
k = 1
(Exam 1)
Step 1: Identify the sorting column
Look at column k = 1
(Exam 1 scores):
- Student 0: score = 6
- Student 1: score = 5
- Student 2: score = 11
- Student 3: score = 7
Step 2: Apply the key function
The lambda function lambda x: -x[k]
transforms each row:
- Student 0:
-x[1]
=-6
- Student 1:
-x[1]
=-5
- Student 2:
-x[1]
=-11
- Student 3:
-x[1]
=-7
Step 3: Sort based on transformed values
Python sorts these negative values in ascending order:
[-11, -7, -6, -5]
This ordering corresponds to the original rows with scores:
[11, 7, 6, 5]
Step 4: Final result The rows are reordered according to this sorting:
Exam0 Exam1 Exam2 Student 2: [8, 11, 2] (highest Exam 1 score: 11) Student 3: [9, 7, 1] (second highest: 7) Student 0: [10, 6, 9] (third highest: 6) Student 1: [7, 5, 3] (lowest: 5)
The students are now arranged from highest to lowest score in Exam 1, with each student's complete row of scores moved as a unit.
Solution Implementation
1class Solution:
2 def sortTheStudents(self, score: List[List[int]], k: int) -> List[List[int]]:
3 """
4 Sort the students (rows) based on their scores in the k-th exam (column) in descending order.
5
6 Args:
7 score: 2D list where score[i][j] represents the score of i-th student in j-th exam
8 k: The index of the exam column to sort by (0-indexed)
9
10 Returns:
11 The sorted 2D list with students ordered by their k-th exam scores in descending order
12 """
13 # Sort the score matrix by the k-th column in descending order
14 # Using negative value (-x[k]) to achieve descending sort
15 sorted_students = sorted(score, key=lambda student_scores: -student_scores[k])
16
17 return sorted_students
18
1class Solution {
2 /**
3 * Sorts students (rows) based on their scores in a specific exam (column k)
4 * in descending order.
5 *
6 * @param score 2D array where score[i][j] represents the score of student i in exam j
7 * @param k the index of the exam column to sort by
8 * @return the sorted 2D array of student scores
9 */
10 public int[][] sortTheStudents(int[][] score, int k) {
11 // Sort the rows of the score matrix based on the k-th column values
12 // Using a custom comparator to sort in descending order
13 Arrays.sort(score, (studentA, studentB) -> studentB[k] - studentA[k]);
14
15 // Return the sorted score matrix
16 return score;
17 }
18}
19
1class Solution {
2public:
3 vector<vector<int>> sortTheStudents(vector<vector<int>>& score, int k) {
4 // Sort the 2D vector of scores based on the k-th column in descending order
5 // Each row represents a student's scores across different exams
6 // We want to sort students by their score in the k-th exam (0-indexed)
7 sort(score.begin(), score.end(), [k](const vector<int>& student_a, const vector<int>& student_b) {
8 // Compare the k-th exam score of two students
9 // Return true if student_a's score is greater (for descending order)
10 return student_a[k] > student_b[k];
11 });
12
13 // Return the sorted score matrix
14 return score;
15 }
16};
17
1/**
2 * Sorts students (represented as score arrays) in descending order based on their score in exam k
3 * @param score - 2D array where each row represents a student and each column represents an exam score
4 * @param k - The index of the exam to sort by (0-indexed)
5 * @returns The sorted 2D array of student scores
6 */
7function sortTheStudents(score: number[][], k: number): number[][] {
8 // Sort the students in descending order based on their score in the k-th exam
9 // For each pair of students (a, b), compare b's k-th exam score with a's k-th exam score
10 // This results in descending order (highest scores first)
11 return score.sort((studentA: number[], studentB: number[]) => {
12 return studentB[k] - studentA[k];
13 });
14}
15
Time and Space Complexity
The time complexity is O(m Γ log m)
, where m
is the number of rows in the score
matrix. This is because the sorted()
function uses Timsort algorithm, which has a time complexity of O(n log n)
for sorting n
elements. In this case, we're sorting m
rows based on the value at index k
in each row.
The space complexity is O(log m)
. While sorted()
creates a new list which would typically require O(m)
space, the space complexity analysis here refers to the auxiliary space used by the sorting algorithm itself. Timsort requires O(log n)
space for its recursive calls and temporary storage during the merge operations. Since we're sorting m
rows, this translates to O(log m)
auxiliary space complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Modifying the Original Matrix Instead of Returning a New One
A common mistake is trying to sort the matrix in-place using list.sort()
instead of sorted()
, which can lead to unexpected behavior if the caller expects the original matrix to remain unchanged.
Incorrect approach:
def sortTheStudents(self, score: List[List[int]], k: int) -> List[List[int]]:
score.sort(key=lambda x: -x[k]) # Modifies the original matrix!
return score
Correct approach:
def sortTheStudents(self, score: List[List[int]], k: int) -> List[List[int]]:
return sorted(score, key=lambda x: -x[k]) # Returns a new sorted matrix
2. Index Out of Bounds Error
Failing to validate that k
is within valid column bounds can cause runtime errors. If k >= n
(where n
is the number of exams), accessing x[k]
will raise an IndexError
.
Solution with validation:
def sortTheStudents(self, score: List[List[int]], k: int) -> List[List[int]]:
# Validate k is within bounds
if not score or not score[0] or k < 0 or k >= len(score[0]):
return score
return sorted(score, key=lambda x: -x[k])
3. Confusion Between Ascending and Descending Order
Forgetting to negate the value in the key function results in ascending order (lowest scores first) instead of the required descending order.
Wrong (ascending order):
sorted(score, key=lambda x: x[k]) # Lowest scores first
Correct (descending order):
sorted(score, key=lambda x: -x[k]) # Highest scores first
4. Using reverse=True
with Positive Values
While using reverse=True
parameter achieves the same result, mixing approaches can lead to confusion when maintaining code.
Alternative (also correct but different style):
sorted(score, key=lambda x: x[k], reverse=True)
Choose one approach consistently throughout your codebase for better readability.
How does merge sort divide the problem into subproblems?
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!