Problem overview
The method leaderboard gets a list of Player records, each with a name and a score. It returns only the names, from the highest score to the lowest. Players with equal scores are ordered alphabetically by name. The lesson provides the record: record Player(String name, int score) {}.
For Ava 30, Ben 25, Cy 40 the result is [Cy, Ava, Ben]. For Mia 50, Leo 70, Ava 50 it is [Leo, Ava, Mia]: Leo leads with 70, and Ava comes before Mia among the two 50s. A single player, Zoe 0, gives [Zoe].
Approach
The job has two parts. First sort the players with a comparator that has two rules, higher score first and then name from A to Z. Then copy the names, in the new order, into a fresh list. Sorting the records and keeping the scores until the end means the names never lose their scores along the way.
Step by step
- Call
players.sortwith a lambda(a, b) -> { ... }that has a body in braces. First rule: ifa.score() != b.score(), returnb.score() - a.score(). The subtraction is written the other way round from an ascending sort. Whenahas more points, the result is negative, soagoes first. - Second rule, for equal scores: return
a.name().compareTo(b.name()), which is alphabetical order. - After the sort, create an empty
List<String>namednamesas a newArrayList. - Loop over the players with
for (Player player : players). They are already in the right order. - Inside the loop, add
player.name()tonames. Only the names go in, not the scores. - Return
namesafter the loop.
The solution in Java
class Solution {
public List<String> leaderboard(List<Player> players) {
players.sort((a, b) -> {
if (a.score() != b.score()) {
return b.score() - a.score();
}
return a.name().compareTo(b.name());
});
List<String> names = new ArrayList<>();
for (Player player : players) {
names.add(player.name());
}
return names;
}
}
Scores are between 0 and 1000, so subtracting them can't overflow. The first example prints as [Cy, Ava, Ben], the second as [Leo, Ava, Mia] and the third as [Zoe].
Edge cases and common mistakes
- Wrong direction.
a.score() - b.score()sorts from the lowest score up. The higher score must make the result negative fora, so the order isbminusa. - Missing tie rule. Without the name comparison, equal scores keep their input order, so
Mia 50, Leo 70, Ava 50would give[Leo, Mia, Ava]. - Comparing names in the wrong direction. The names use
a.name().compareTo(b.name()), ascending, even though the scores are descending. The two rules go in different directions. - Sorting a list that can't change.
sortreorders the list in place, so a list that can't be modified, such as one made withList.of(...), throwsUnsupportedOperationException. - Returning records. The method returns a list of names. Returning
playerswould hand back whole records.
Complexity
Sorting takes O(n log n) comparisons for n players, and the copy loop is O(n), so the sort dominates. The new list of names uses O(n) extra space.
Testing
Try the lesson's examples and a few of your own:
Ava 30, Ben 25, Cy 40gives[Cy, Ava, Ben].Mia 50, Leo 70, Ava 50gives[Leo, Ava, Mia].Zoe 0gives[Zoe].
Names are unique, so two players never tie on both rules, and the order of the result is fully decided. Also try a list where every player has the same score. The first rule never applies, and the result is simply the names from A to Z.
