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 largestLogic
- Handle edge cases — empty list or all same values
- Track two variables —
largestandsecond_largest - Loop through every number
- If current number is greater than
largest— update both - If current number is less than
largestbut greater thansecond_largest— updatesecond_largest - Return
second_largest
Flow
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])) # NoneCode Execution — Solution 1
Trace through second_largest([3, 1, 9, 7, 5]):
| Step | number | number > largest? | number > second and != largest? | largest | second |
|---|---|---|---|---|---|
| Start | — | — | — | -inf | -inf |
| 1st | 3 | Yes | — | 3 | -inf |
| 2nd | 1 | No | 1 > -inf and 1 != 3 → Yes | 3 | 1 |
| 3rd | 9 | Yes | — | 9 | 3 |
| 4th | 7 | No | 7 > 3 and 7 != 9 → Yes | 9 | 7 |
| 5th | 5 | No | 5 > 7? → No | 9 | 7 |
| Done | 9 | 7 |
Result: 7
Trace through second_largest([10, 10, 9, 8]):
| Step | number | > largest? | > second and != largest? | largest | second |
|---|---|---|---|---|---|
| Start | — | — | — | -inf | -inf |
| 1st | 10 | Yes | — | 10 | -inf |
| 2nd | 10 | No | 10 != 10 → No (duplicate) | 10 | -inf |
| 3rd | 9 | No | 9 > -inf and 9 != 10 → Yes | 10 | 9 |
| 4th | 8 | No | 8 > 9? → No | 10 | 9 |
| Done | 10 | 9 |
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])) # 9Code Execution — Solution 2
Trace through second_largest([10, 10, 9, 8]):
| Step | Code | Result |
|---|---|---|
| Input | numbers | [10, 10, 9, 8] |
| Remove duplicates | set(numbers) | {8, 9, 10} |
| To list | list(...) | [8, 9, 10] |
| Sort descending | .sort(reverse=True) | [10, 9, 8] |
| Second element | unique[1] | 9 |
Trace through second_largest([5, 5, 5, 5]):
| Step | Code | Result |
|---|---|---|
| Remove duplicates | set([5,5,5,5]) | {5} |
| Length check | len({5}) < 2 | True |
| Return | None |
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])) # 9Code Execution — Solution 3
Trace through second_largest([3, 1, 9, 7, 5]):
| Step | Code | Result |
|---|---|---|
| Find largest | max([3, 1, 9, 7, 5]) | 9 |
| Remove all 9s | [n for n in numbers if n != 9] | [3, 1, 7, 5] |
| Find max of remaining | max([3, 1, 7, 5]) | 7 |
| Return | 7 |
Trace through second_largest([10, 10, 9, 8]):
| Step | Code | Result |
|---|---|---|
| Find largest | max([10, 10, 9, 8]) | 10 |
| Remove all 10s | [n for n in numbers if n != 10] | [9, 8] |
| Find max of remaining | max([9, 8]) | 9 |
| Return | 9 |
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])) # 9Code Execution — Solution 4
Trace through second_largest([3, 1, 9, 7, 5]):
| Step | Code | Result |
|---|---|---|
| Remove duplicates | set([3,1,9,7,5]) | {1, 3, 5, 7, 9} |
| Length check | len >= 2 | Pass |
| 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?
| Solution | How | Best when |
|---|---|---|
| Solution 1 | Track two variables in one loop | Most efficient — one pass, no extra memory |
| Solution 2 | Set + sort | Simple and readable |
| Solution 3 | Remove max then find max | Easy to understand conceptually |
| Solution 4 | heapq.nlargest | Large datasets where efficiency matters |
Output
7
200
None
-2
9
None