Problem overview
The function topScorer gets scores, a map from names to scores, and returns the name with the highest score. When several players share the top score, it returns the name that comes first alphabetically. The map has at least one name, and every score is from 0 to 100.
With {"Ana": 90, "Ben": 75, "Cara": 88} the answer is Ana. With {"Zoe": 82, "Ana": 82} both players tie, so the answer is Ana. With {"Max": 0} the only player wins, even with a score of 0.
Approach
Keep the best player seen so far, and compare every entry with it. This is the same pattern as finding the largest number in a list, with one extra rule for ties. A map has no fixed order, so the answer must not depend on which entry the loop reaches first. That is why the tie rule compares names instead of relying on position.
Step by step
- Create two
varvariables:bestName, an empty string, andbestScore, set to -1. Every score is at least 0, so the first player always beats -1 and takes the lead. - Loop over the entries with
for ((name, score) in scores), splitting each into a name and a score. - Inside, check whether this player is better: their score is higher than
bestScore, or the scores are equal andnamecomes beforebestName. Comparing two strings with<uses alphabetical (dictionary) order. - If so, store this name and score as the new best.
- After the loop, return
bestName.
The solution in Kotlin
class Solution {
fun topScorer(scores: MutableMap<String, Int>): String {
var bestName = ""
var bestScore = -1
for ((name, score) in scores) {
if (score > bestScore || (score == bestScore && name < bestName)) {
bestName = name
bestScore = score
}
}
return bestName
}
}
The parentheses around the tie check make it explicit that it counts only when the two scores are equal. Kotlin compares strings with < by their characters in order, which is what the lesson needs for names that are a capital letter followed by lowercase letters.
The three examples print:
Ana
Ana
Max
Putting Ana and Zoe into the map in the other order also gives Ana, because the tie rule decides, not the order.
Following the loop
For the first example, with the entries visited in the order Ana, Ben, Cara, the best player after each entry is:
Ana 90 -> best is Ana 90
Ben 75 -> best is Ana 90
Cara 88 -> best is Ana 90
Ana beats the starting -1 and takes the lead. Ben has 75 and Cara has 88, and neither is higher than 90, so Ana stays in front and is returned. The same loop works on any map size, because it looks at each entry exactly once and keeps only two variables.
Edge cases and common mistakes
- Starting
bestScoreat 0. With{"Max": 0}, the score 0 is not higher than 0, and the name"Max"does not come before the empty string, so the function returns"". Starting at -1 fixes this. - Dropping the tie rule. With only
score > bestScore, the winner of a tie is whichever entry the loop meets first. For a map built as"Zoe" to 82, "Ana" to 82the function returnsZoe, and for the reverse orderAna. The tests expectAnaboth times. - Missing the parentheses around the tie check, so the name comparison applies to more than ties.
- Declaring the best values with
val. They change inside the loop, so they needvar.
