Start learning free

LESSON 227 OF 677 · LOOPS WITH STRINGS, ARRAYS & DICTIONARIES

Top Scorer in Kotlin: Looping Over a Map

Practice Read the full explanation

You get scores, a HashMap from players' names to their scores. Return the name of the player with the highest score.

Several players may share the highest score. Then return the name that comes first in alphabetical order.

 

Example 1:

Input: scores = {"Ana": 90, "Ben": 75, "Cara": 88}
Output: "Ana"
Explanation: 90 is the highest score, and it is Ana's.

Example 2:

Input: scores = {"Zoe": 82, "Ana": 82}
Output: "Ana"
Explanation: Both have 82. "Ana" comes before "Zoe" in alphabetical order.

Example 3:

Input: scores = {"Max": 0}
Output: "Max"
Explanation: Max is the only player, so his score is the highest.

 

Constraints:

  • scores has at least one name.
  • Every score is a whole number from 0 to 100.
  • Each name is a capital letter followed by lowercase letters, like "Ana".
STEP 1 OF 5
    Ctrl + Enter to check

    KOTLIN · LOOPS WITH STRINGS, ARRAYS & DICTIONARIES

    Top Scorer in Kotlin, explained

    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

    1. Create two var variables: bestName, an empty string, and bestScore, set to -1. Every score is at least 0, so the first player always beats -1 and takes the lead.
    2. Loop over the entries with for ((name, score) in scores), splitting each into a name and a score.
    3. Inside, check whether this player is better: their score is higher than bestScore, or the scores are equal and name comes before bestName. Comparing two strings with < uses alphabetical (dictionary) order.
    4. If so, store this name and score as the new best.
    5. 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 bestScore at 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 82 the function returns Zoe, and for the reverse order Ana. The tests expect Ana both 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 need var.
    Keep going with Kotlin500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free