DocsHub
PythonIntermediate

Second Largest Number

Learn how to find the second largest number in a list in Python.

Second Largest Number

Problem

Given a list of numbers, find the second largest number. The second largest is the largest number that is smaller than the maximum.

Input:  [3, 1, 9, 7, 5]
Output: 7

Input:  [100, 200, 50, 300, 150]
Output: 200

Input:  [5, 5, 5, 5]
Output: None  — no second largest, all numbers are the same

Input:  [-1, -5, -3, -2]
Output: -2

Input:  [10, 10, 9, 8]
Output: 9  — ignore duplicates of the largest

Logic

  1. Handle edge cases — empty list or all same values
  2. Track two variables — largest and second_largest
  3. Loop through every number
  4. If current number is greater than largest — update both
  5. If current number is less than largest but greater than second_largest — update second_largest
  6. Return second_largest

Flow

Yes No Yes No Yes No Yes No Start largest = -infinitysecond = -infinity Take each number number > largest? second = largestlargest = number number > secondAND number != largest? second = number Skip More numbers? second still -infinity? Return None Return second

Solution 1 — tracking two variables

Loop once and track both the largest and second largest at the same time.

def second_largest(numbers):
    # handle edge case — need at least 2 unique values
    if len(numbers) < 2:
        return None

    # start both at negative infinity
    # so any real number will be greater
    largest = float("-inf")
    second = float("-inf")

    for number in numbers:
        if number > largest:
            # new largest found
            # old largest becomes the new second largest
            second = largest
            largest = number
        elif number > second and number != largest:
            # not the largest but bigger than current second
            # and not a duplicate of the largest
            second = number

    # if second is still -infinity — no second largest exists
    if second == float("-inf"):
        return None

    return second


print(second_largest([3, 1, 9, 7, 5]))        # 7
print(second_largest([100, 200, 50, 300, 150])) # 200
print(second_largest([5, 5, 5, 5]))            # None
print(second_largest([-1, -5, -3, -2]))        # -2
print(second_largest([10, 10, 9, 8]))          # 9
print(second_largest([42]))                    # None

Code Execution — Solution 1

Trace through second_largest([3, 1, 9, 7, 5]):

Stepnumbernumber > largest?number > second and != largest?largestsecond
Start-inf-inf
1st3Yes3-inf
2nd1No1 > -inf and 1 != 3 → Yes31
3rd9Yes93
4th7No7 > 3 and 7 != 9 → Yes97
5th5No5 > 7? → No97
Done97

Result: 7

Trace through second_largest([10, 10, 9, 8]):

Stepnumber> largest?> second and != largest?largestsecond
Start-inf-inf
1st10Yes10-inf
2nd10No10 != 10 → No (duplicate)10-inf
3rd9No9 > -inf and 9 != 10 → Yes109
4th8No8 > 9? → No109
Done109

Result: 9

float("-inf") is negative infinity — it is smaller than every number. Starting largest and second here means the first real number we encounter will always be greater, so both get initialized correctly without any special cases.


Solution 2 — using a sorted set

Convert to a set to remove duplicates, sort in descending order, and pick the second element.

def second_largest(numbers):
    # remove duplicates using set
    unique = list(set(numbers))

    # need at least 2 unique values
    if len(unique) < 2:
        return None

    # sort in descending order
    unique.sort(reverse=True)

    # second element is the second largest
    return unique[1]


print(second_largest([3, 1, 9, 7, 5]))          # 7
print(second_largest([100, 200, 50, 300, 150]))  # 200
print(second_largest([5, 5, 5, 5]))              # None
print(second_largest([-1, -5, -3, -2]))          # -2
print(second_largest([10, 10, 9, 8]))            # 9

Code Execution — Solution 2

Trace through second_largest([10, 10, 9, 8]):

StepCodeResult
Inputnumbers[10, 10, 9, 8]
Remove duplicatesset(numbers){8, 9, 10}
To listlist(...)[8, 9, 10]
Sort descending.sort(reverse=True)[10, 9, 8]
Second elementunique[1]9

Trace through second_largest([5, 5, 5, 5]):

StepCodeResult
Remove duplicatesset([5,5,5,5]){5}
Length checklen({5}) < 2True
ReturnNone

Solution 3 — remove max and find max again

Find the largest, remove it, find the largest of what remains.

def second_largest(numbers):
    if len(numbers) < 2:
        return None

    # remove all occurrences of the largest
    largest = max(numbers)
    remaining = [n for n in numbers if n != largest]

    # if nothing left — all numbers were the same
    if not remaining:
        return None

    return max(remaining)


print(second_largest([3, 1, 9, 7, 5]))          # 7
print(second_largest([100, 200, 50, 300, 150]))  # 200
print(second_largest([5, 5, 5, 5]))              # None
print(second_largest([-1, -5, -3, -2]))          # -2
print(second_largest([10, 10, 9, 8]))            # 9

Code Execution — Solution 3

Trace through second_largest([3, 1, 9, 7, 5]):

StepCodeResult
Find largestmax([3, 1, 9, 7, 5])9
Remove all 9s[n for n in numbers if n != 9][3, 1, 7, 5]
Find max of remainingmax([3, 1, 7, 5])7
Return7

Trace through second_largest([10, 10, 9, 8]):

StepCodeResult
Find largestmax([10, 10, 9, 8])10
Remove all 10s[n for n in numbers if n != 10][9, 8]
Find max of remainingmax([9, 8])9
Return9

Solution 4 — using heapq

Python's heapq.nlargest() returns the N largest unique values efficiently.

import heapq

def second_largest(numbers):
    # get 2 largest unique values
    unique = list(set(numbers))

    if len(unique) < 2:
        return None

    # nlargest(2, ...) returns [largest, second_largest]
    two_largest = heapq.nlargest(2, unique)
    return two_largest[1]


print(second_largest([3, 1, 9, 7, 5]))          # 7
print(second_largest([100, 200, 50, 300, 150]))  # 200
print(second_largest([5, 5, 5, 5]))              # None
print(second_largest([-1, -5, -3, -2]))          # -2
print(second_largest([10, 10, 9, 8]))            # 9

Code Execution — Solution 4

Trace through second_largest([3, 1, 9, 7, 5]):

StepCodeResult
Remove duplicatesset([3,1,9,7,5]){1, 3, 5, 7, 9}
Length checklen >= 2Pass
nlargest(2)heapq.nlargest(2, [1,3,5,7,9])[9, 7]
Second element[9, 7][1]7

heapq.nlargest(n, iterable) is efficient when you need the top N values from a large list. It does not sort the entire list — it uses a heap internally which is faster for this specific task on large datasets.


Which solution to use?

SolutionHowBest when
Solution 1Track two variables in one loopMost efficient — one pass, no extra memory
Solution 2Set + sortSimple and readable
Solution 3Remove max then find maxEasy to understand conceptually
Solution 4heapq.nlargestLarge datasets where efficiency matters

Output

7
200
None
-2
9
None

On this page