LeetCode #506 Easy

Relative Ranks

Relative Ranks: rank athletes by score and label the top three with medals, keeping output in the original order.

Constraints
  • n == score.length
  • 1 <= n <= 10⁴
  • 0 <= score[i] <= 10⁶
  • All the values in score are unique.
heapsortingarray
Open on LeetCode ↗
02

Intuition

Relative ranks assigns placement labels to athletes by score: the top three receive medal names and the rest receive their numeric position. The complication is that the output must be in the original athlete order, while ranks are determined by sorted order. Sorting the scores directly loses the association between a score and its athlete. So the indices must travel with the values: - Sort the indices by their scores descending, so position k in the sorted result tells you which original athlete finished k + 1. Walking that sorted list, the first three indices get "Gold Medal", "Silver Medal", and "Bronze Medal", and index k beyond that receives the string of k + 1. Writing to result[originalIndex] is what restores the original ordering — the answer array is filled out of order and read in order. The medal strings must be exact, including the space and capitalisation. "Gold" alone is a wrong answer, and it is a frustrating one to debug since the logic is otherwise correct. Ranks are 1-based while indices are 0-based, so the numeric label is k + 1. Off-by-one here shifts every non-medal athlete. Sorting descending matters — the highest score is rank 1. Ascending order silently produces reversed rankings. A max-heap is an alternative: push all index-score pairs and pop n times, assigning ranks in pop order. Same O(n log n), no advantage here. Scores are guaranteed unique, so no tie-breaking rule is needed.

How to spot this pattern

Sort index-score pairs by score descending, then write each rank back to its original index. Carrying the index through the sort is what lets the answer be assembled in the input's order rather than the sorted one.

03

Approach

Try it first

Before reading on: price up what enumerating every case costs here, then ask why only the extreme element matters and the rest need no ordering. Aim for O(n log n) time and O(n) space.

1

Keep indices with scores

Sorting scores alone loses which athlete owns each score. Sort indices by their score instead, so the association survives.

2

Sort descending

The highest score is rank 1, so sort in decreasing order. Ascending order silently produces reversed rankings that pass no test.

3

Assign the three medals

The first three sorted positions receive "Gold Medal", "Silver Medal", "Bronze Medal". The exact strings matter — "Gold" alone is wrong.

4

Number the rest

Position k beyond the medals gets the string of k + 1, since ranks are 1-based while indices are 0-based.

5

Write to the original index

Store each label at result[originalIndex]. The array is filled out of order and read in order, which is what restores the athlete sequence.

6

Cost of the approach

Sorting dominates at O(n log n) time, with O(n) space for the index array and result. Scores are unique, so no tie-breaking is needed.

04

Solution & live demo

▶1class Solution:
▶2 def findRelativeRanks(self, score:
▶3 List[int]) -> List[str]:
▶4 pairs = sorted(enumerate(score), key=lambda p: -p[1])
▶5 answer = [''] * len(score)
▶6 medals = ['Gold Medal', 'Silver Medal', 'Bronze Medal']
▶7 for rank, (orig_i, s) in enumerate(pairs):
▶8 answer[orig_i] = medals[rank] if rank < 3 else str(rank + 1)
▶9 return answer
05

Common pitfalls

Losing the original index

✗ Wrong
sorted_scores = sorted(score, reverse=True)
# then no way back to input positions
✓ Right
pairs = sorted(enumerate(score), key=lambda p: -p[1])
answer[orig_i] = ...

The output must line up with the input array, but ranking requires sorted order. Pairing each score with its index preserves the mapping through the sort.

Off-by-one on the numeric rank

✗ Wrong
answer[orig_i] = str(rank)
✓ Right
answer[orig_i] = str(rank + 1)

Enumeration is zero-based but ranks start at 1, and the fourth-place athlete must read "4". The medals hide the error for the first three, so it only shows up from position four onward.

Sorting ascending and reversing the medal logic

✗ Wrong
pairs = sorted(enumerate(score), key=lambda p: p[1])
medals for the LAST three
✓ Right
key=lambda p: -p[1]
medals[rank] if rank < 3

Two inversions to reason about instead of none, and the numeric ranks then need len - rank arithmetic. Sorting descending makes rank and position the same thing.

06

Edge cases

single athlete

the lone score gets 'Gold Medal' regardless of its value

fewer than three athletes

only as many medal labels are assigned as there are athletes; no bronze if there are only two

scores already sorted descending

the sort is a no-op but pairing with indices still happens the same way

large gaps between scores

ranking depends only on relative order, not on the numeric gaps between scores

07

Complexity

Time
O(n log n)
Space
O(n)
dominated by sorting the (score, index) pairs; writing the answer back is O(n).