{x}
blog image

Rank Scores

Table: Scores

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| score       | decimal |
+-------------+---------+
id is the primary key (column with unique values) for this table.
Each row of this table contains the score of a game. Score is a floating point value with two decimal places.

 

Write a solution to find the rank of the scores. The ranking should be calculated according to the following rules:

  • The scores should be ranked from the highest to the lowest.
  • If there is a tie between two scores, both should have the same ranking.
  • After a tie, the next ranking number should be the next consecutive integer value. In other words, there should be no holes between ranks.

Return the result table ordered by score in descending order.

The result format is in the following example.

 

Example 1:

Input: 
Scores table:
+----+-------+
| id | score |
+----+-------+
| 1  | 3.50  |
| 2  | 3.65  |
| 3  | 4.00  |
| 4  | 3.85  |
| 5  | 4.00  |
| 6  | 3.65  |
+----+-------+
Output: 
+-------+------+
| score | rank |
+-------+------+
| 4.00  | 1    |
| 4.00  | 1    |
| 3.85  | 2    |
| 3.65  | 3    |
| 3.65  | 3    |
| 3.50  | 4    |
+-------+------+

Solution Explanation for LeetCode 178. Rank Scores

This problem requires ranking scores from highest to lowest, handling ties by assigning the same rank to tied scores and ensuring no gaps in the ranking sequence. We'll explore two solutions: one using window functions (efficient and concise) and another using variables (more complex but demonstrates a different approach).

Solution 1: Using Window Functions (MySQL and Pandas)

This solution leverages the power of window functions, which are highly efficient for ranking tasks.

MySQL

SELECT
    score,
    DENSE_RANK() OVER (ORDER BY score DESC) AS 'rank'
FROM Scores;
  • DENSE_RANK() OVER (ORDER BY score DESC): This is the core of the solution. DENSE_RANK() assigns ranks without gaps. OVER (ORDER BY score DESC) specifies that the ranking should be done in descending order of the score column. The result is a new column rank containing the calculated ranks.

Python (Pandas)

import pandas as pd
 
def order_scores(scores: pd.DataFrame) -> pd.DataFrame:
    scores["rank"] = scores["score"].rank(method="dense", ascending=False)
    result_df = scores.drop("id", axis=1).sort_values(by="score", ascending=False)
    return result_df
  • scores["score"].rank(method="dense", ascending=False): This line uses Pandas' rank() function to achieve the same result as DENSE_RANK() in MySQL. method="dense" ensures no gaps in ranks, and ascending=False ranks from highest to lowest.

Time Complexity: O(N log N) for Pandas (due to sorting), O(N) for MySQL (window functions are optimized). N is the number of rows in the Scores table.

Space Complexity: O(N) for Pandas (to store the DataFrame), O(N) for MySQL (to store the result set).

Solution 2: Using Variables (MySQL)

This approach uses MySQL variables to simulate the ranking process. It's less efficient but demonstrates a different way to achieve the result.

SELECT
    Score,
    CONVERT(rk, SIGNED) `Rank`
FROM
    (
        SELECT
            Score,
            IF(@latest = Score, @rank, @rank := @rank + 1) rk,
            @latest := Score
        FROM
            Scores,
            (
                SELECT
                    @rank := 0,
                    @latest := NULL
            ) tmp
        ORDER BY
            Score DESC
    ) s;
  • @rank := 0, @latest := NULL: These lines initialize two user-defined variables: @rank to track the current rank and @latest to store the previously processed score.

  • IF(@latest = Score, @rank, @rank := @rank + 1): This is the crucial part. It checks if the current Score is the same as the @latest score. If they are equal (a tie), it keeps the same rank (@rank). Otherwise, it increments @rank and assigns the new rank.

  • @latest := Score: This updates @latest with the current Score for the next comparison.

  • ORDER BY Score DESC: The outer query sorts the results in descending order of score.

Time Complexity: O(N log N) due to the ORDER BY clause.

Space Complexity: O(N) for the result set.

Conclusion:

The solution using window functions (Solution 1) is generally preferred due to its better performance and readability. Solution 2 is provided for illustrative purposes to show an alternative approach, but it's less efficient than the window function approach. Choose the solution that best suits your needs and understanding; for most cases, the window function approach is recommended.