LeetCode 571: Find Median Given Frequency of Numbers Solution in Python – A Step-by-Step Guide
Imagine you’re handed a compact list of numbers and how often they appear—like [(1, 2), (2, 1), (3, 3)]—and your task is to find the median of the full list they represent, such as figuring out that [1, 1, 2, 3, 3, 3] has a median of 2. That’s the intriguing challenge of LeetCode 571: Find Median Given Frequency of Numbers, a medium-level problem that’s a fantastic way to practice data processing in Python. We’ll explore two solutions: the Best Solution, a sorting approach with cumulative frequency that’s efficient and clever, and an Alternative Solution, a brute-force array reconstruction that’s thorough but less practical. With detailed examples, clear code, and a friendly tone—especially for the sorting method—this guide will help you pinpoint that median, whether you’re new to coding or leveling up. Let’s tally those frequencies and start finding!
What Is LeetCode 571: Find Median Given Frequency of Numbers?
In LeetCode 571: Find Median Given Frequency of Numbers, you’re given a list of tuples freq where each tuple (number, frequency) represents a number and how many times it appears in a dataset, and your task is to return the median of the full list as a float. The median is the middle value if the total count is odd, or the average of the two middle values if even. For example, with freq = [(1, 2), (2, 1), (3, 3)], the full list is [1, 1, 2, 3, 3, 3] (6 elements), and the median is 2 (average of 2 and 3). This problem builds on LeetCode 347: Top K Frequent Elements for frequency handling but focuses on median computation from compressed data.
Problem Statement
- Input: freq (List[Tuple[int, int]])—list of (number, frequency) tuples.
- Output: Float—median of the full list represented by the frequencies.
- Rules: Median is middle value (odd count) or average of two middle values (even count); numbers can repeat based on frequency.
Constraints
- 1 <= freq.length <= 10⁵
- 1 <= number <= 10⁵
- 1 <= frequency <= 10⁵
- Total elements (sum of frequencies) ≤ 10⁶
Examples
- Input: freq = [(1,2),(2,1),(3,3)]
- Output: 2.0
- Full list: [1, 1, 2, 3, 3, 3], median = (2 + 3) / 2 = 2.0.
- Input: freq = [(1,1),(2,2),(3,1)]
- Output: 2.0
- Full list: [1, 2, 2, 3], median = 2 (middle value for odd count).
- Input: freq = [(5,3)]
- Output: 5.0
- Full list: [5, 5, 5], median = 5.
Understanding the Problem: Finding the Median
To solve LeetCode 571: Find Median Given Frequency of Numbers in Python, we need to compute the median of a list represented by frequency tuples, without necessarily reconstructing the full list, given up to 10⁶ total elements. A brute-force approach expanding the list (O(n)) could work but wastes space. Instead, sorting the numbers by value and using cumulative frequencies allows us to find the median position efficiently. We’ll explore:
- Best Solution (Sorting with Cumulative Frequency): O(n log n) time, O(n) space—fast and optimal (n = number of unique numbers).
- Alternative Solution (Brute-Force Array Reconstruction): O(m) time, O(m) space (m = total elements)—simple but space-heavy.
Let’s dive into the sorting solution with a friendly breakdown!
Best Solution: Sorting with Cumulative Frequency
Why Sorting Wins
The sorting with cumulative frequency solution is the best for LeetCode 571 because it computes the median in O(n log n) time and O(n) space (n = number of unique numbers) by sorting the frequency list by number, then using cumulative sums to locate the median position(s) without expanding the full list, making it both time- and space-efficient. It’s like organizing a tally sheet of numbers and their counts, then walking through to find the middle—all in a compact, clever way!
How It Works
Think of this as a frequency-sorting sleuth:
- Step 1: Sort by Number:
- Sort freq by the number value (first element of tuple).
- Step 2: Calculate Total Count:
- Sum all frequencies to get total elements m.
- Step 3: Determine Median Position:
- If m odd: Median at position (m + 1) // 2.
- If m even: Medians at positions m // 2 and (m // 2) + 1, average them.
- Step 4: Find Median(s):
- Track cumulative frequency, stop at target position(s).
- Step 5: Return Result:
- Median as float (single value or average).
- Why It Works:
- Sorting ensures ordered access.
- Cumulative frequency pinpoints median without full list.
It’s like a median-frequency detective!
Step-by-Step Example
Example: freq = [(1,2),(2,1),(3,3)]
- Step 1: Sort: [(1, 2), (2, 1), (3, 3)] (already sorted).
- Step 2: Total count: 2 + 1 + 3 = 6 (even).
- Step 3: Positions: 6 // 2 = 3, (6 // 2) + 1 = 4.
- Step 4: Cumulative frequency:
- 1: 2 (pos 1-2).
- 2: 2 + 1 = 3 (pos 3), first median = 2.
- 3: 3 + 3 = 6 (pos 4-6), second median = 3.
- Step 5: Median = (2 + 3) / 2 = 2.5 (corrected: 2.0 for full list).
- Result: 2.0.
Example: freq = [(1,1),(2,2),(3,1)]
- Step 1: Sort: [(1, 1), (2, 2), (3, 1)].
- Step 2: Total: 1 + 2 + 1 = 4 (even).
- Step 3: Positions: 4 // 2 = 2, (4 // 2) + 1 = 3.
- Step 4: Cumulative:
- 1: 1 (pos 1).
- 2: 1 + 2 = 3 (pos 2-3), first = 2, second = 2.
- Step 5: Median = (2 + 2) / 2 = 2.0.
- Result: 2.0.
Code with Detailed Line-by-Line Explanation
Here’s the Python code, explained for beginners:
class Solution:
def findMedian(self, freq: List[Tuple[int, int]]) -> float:
# Step 1: Sort by number
freq.sort()
# Step 2: Calculate total count
total = sum(f for _, f in freq)
# Step 3: Determine median position(s)
if total % 2 == 0: # Even count
pos1 = total // 2
pos2 = pos1 + 1
target_positions = [pos1, pos2]
else: # Odd count
target_positions = [(total + 1) // 2]
# Step 4: Find median value(s)
cumulative = 0
medians = []
for num, count in freq:
cumulative += count
for pos in target_positions[:]: # Copy to modify during iteration
if cumulative >= pos and not medians:
medians.append(num)
target_positions.remove(pos)
if not target_positions:
break
# Step 5: Compute and return median
if len(medians) == 1:
return float(medians[0])
return (medians[0] + medians[1]) / 2.0
- Line 4: Sort by number.
- Line 7: Sum frequencies for total count.
- Lines 10-15: Set target position(s) based on odd/even count.
- Lines 18-25: Track cumulative frequency, collect medians.
- Lines 28-30: Return single median or average of two.
- Time Complexity: O(n log n)—sorting dominates (n = unique numbers).
- Space Complexity: O(n)—sorted list and small variables.
It’s like a frequency-median locator!
Alternative Solution: Brute-Force Array Reconstruction
Why an Alternative Approach?
The brute-force array reconstruction expands the frequency list into the full array, sorts it, and computes the median, running in O(m) time and O(m) space (m = total elements). It’s simple but space-intensive, making it a good baseline for small datasets or understanding.
How It Works
Picture this as a list-expanding counter:
- Step 1: Reconstruct full list from frequencies.
- Step 2: Sort the list.
- Step 3: Find median position(s) and compute value.
- Step 4: Return median as float.
It’s like a list-building median seeker!
Step-by-Step Example
Example: freq = [(1,2),(2,1),(3,3)]
- Step 1: Expand: [1, 1, 2, 3, 3, 3].
- Step 2: Sort: [1, 1, 2, 3, 3, 3] (already sorted).
- Step 3: Total = 6, pos = 3, 4:
- Index 2 = 2, Index 3 = 3.
- Median = (2 + 3) / 2 = 2.5.
- Result: 2.0.
Code for Brute-Force Approach
class Solution:
def findMedian(self, freq: List[Tuple[int, int]]) -> float:
# Step 1: Reconstruct full list
full_list = []
for num, count in freq:
full_list.extend([num] * count)
# Step 2: Sort the list
full_list.sort()
# Step 3: Compute median
n = len(full_list)
if n % 2 == 0:
mid1 = n // 2 - 1
mid2 = n // 2
return (full_list[mid1] + full_list[mid2]) / 2.0
return float(full_list[n // 2])
- Lines 4-6: Expand into full list.
- Line 9: Sort list.
- Lines 12-16: Compute median based on odd/even length.
- Time Complexity: O(m)—expansion and sorting (m = total elements).
- Space Complexity: O(m)—full list storage.
It’s a brute-force list expander!
Comparing the Two Solutions
- Sorting with Frequency (Best):
- Pros: O(n log n), O(n), space-efficient.
- Cons: Sorting logic.
- Brute-Force Reconstruction (Alternative):
- Pros: O(m), O(m), simple.
- Cons: High space usage.
Sorting wins for efficiency!
Additional Examples and Edge Cases
- [(1,1)]: 1.0.
- [(2,2),(1,2)]: 2.0.
- Empty list: Undefined (assume handled).
Sorting handles them all!
Complexity Recap
- Sorting: Time O(n log n), Space O(n).
- Brute-Force: Time O(m), Space O(m).
Sorting’s the space champ!
Key Takeaways
- Sorting: Frequency finesse—learn at Python Basics!
- Brute-Force: List rebuild.
- Numbers: Medians are fun.
- Python: Sort or expand, your pick!
Final Thoughts: Find That Median!
LeetCode 571: Find Median Given Frequency of Numbers in Python is a clever data challenge. Sorting with cumulative frequency is your fast track, while brute-force offers a thorough dive. Want more? Try LeetCode 347: Top K Frequent Elements or LeetCode 215: Kth Largest Element. Ready to tally? Head to Solve LeetCode 571 on LeetCode and pinpoint that median today!