The Runner-Up

An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
easy
Seniority
L5
Asked in
Gemini

Problem

A leaderboard already highlights the top score, and the product team wants to show the runner-up beside it. Given a list of scores, return the second-largest distinct value, or None when no runner-up exists.

Not the winner. The one just behind it.

Example 1

Input:

nums = [10,20,30,20,10]

Output:

20

Example 2

Input:

nums = [5,5,5]

Output:

null

Worked solution and explanation

What this really is

This is a distinctness problem wearing a 'find the second biggest' costume, and the whole thing lives in one word: distinct. Anyone can find the max. Candidates stumble when they read 'second largest' as 'the second-biggest element' and forget that a tie at the top is not a runner-up. Hand them [5, 5, 5] and they confidently return 5, when the right answer is None because there is no second distinct value at all.

The trap, concretely

The tempting one-liner is sorted(nums, reverse=True)[1]. On [10, 20, 30, 20, 10] it returns 20, which is correct here by luck. Now try [30, 30, 10]: sorted descending is [30, 30, 10], index 1 is 30, and you have just declared the largest value its own runner-up. Worse, that shape can never return None. The fix is not a smarter sort, it is collapsing duplicates first so a repeated maximum only counts once.

Naive: sort and index
sorted([5, 5, 3], reverse=True)[1] returns 5. The duplicate max fills position 1, so the winner becomes its own runner-up, and this form never yields None.
Correct: dedup, then rank
sorted(set([5, 5, 3])) is [3, 5]; index -2 is 3, the real runner-up. When the set collapses to a single value, a length check returns None.

How to get there

Step 1: Collapse the duplicates

Wrap nums in a set. Every repeat of any value, including the maximum, now counts exactly once. This single step is what separates a passing answer from the buggy one.

Step 2: Rank what remains

Sort the distinct values ascending. The largest distinct value lands at index -1, and the runner-up sits right behind it at index -2. Negative values sort correctly, so nothing special is needed for scores below zero.

Step 3: Guard the None case

If fewer than two distinct values survived, there is no runner-up, so return None. This is the guard that makes all-equal inputs like [5, 5, 5] behave. Only then is it safe to index -2.


The solution

Dedup, then take the second-highest
def the_runner_up(nums):
    ranked = sorted(set(nums))
    if len(ranked) < 2:
        return None
    return ranked[-2]

Common follow-up questions