LeetCode 570 - Managers with at Least 5 Direct Reports
The Employee table represents a company hierarchy. Every row corresponds to one employee and contains four pieces of information: Column Meaning --- --- id Unique employee identifier name Employee name department Department the employee belongs to managerId The id of this…
Difficulty: 🟡 Medium
Topics: Database
Solution
Problem Understanding
The Employee table represents a company hierarchy. Every row corresponds to one employee and contains four pieces of information:
| Column | Meaning |
|---|---|
id |
Unique employee identifier |
name |
Employee name |
department |
Department the employee belongs to |
managerId |
The id of this employee’s manager |
If managerId is NULL, the employee does not report to anyone and is therefore at the top level of the organization.
The problem asks us to find all managers who have at least five direct reports. A direct report means an employee whose managerId points directly to that manager’s id.
The important detail is that only direct reports count. Indirect reports, such as employees further down the hierarchy, should not be included.
For example:
- If employee
101manages employees102,103,104,105, and106, then employee101has five direct reports. - If employee
102manages additional people underneath them, those employees do not count toward employee101’s total.
The expected output is a table containing only the names of managers who satisfy the condition.
The input guarantees several important properties:
idis unique.managerIdreferences another employee’sid, or isNULL.- No employee manages themselves.
These guarantees simplify the problem because we do not need to handle invalid references or cycles involving self-management.
Several edge cases are important:
- Employees with
NULLasmanagerIdmay still be managers if others report to them. - Employees with exactly five reports should be included.
- Employees with fewer than five reports should not appear.
- Multiple managers may satisfy the condition.
- A manager might belong to any department, the department column is irrelevant for this problem.
- Employees without any direct reports should never appear in the result.
Approaches
Brute Force Approach
A brute-force solution would examine every employee and count how many employees report to them.
For each employee:
- Scan the entire table.
- Count rows where
managerId == current_employee.id. - If the count is at least five, include the employee’s name.
This works because every possible reporting relationship is checked explicitly.
However, this approach is inefficient because for every employee we perform another full scan of the table. If there are n employees, the total work becomes O(n^2).
With larger datasets, repeatedly scanning the same table becomes unnecessarily expensive.
Optimal Approach
The key observation is that we only need the number of employees grouped by managerId.
Instead of repeatedly counting reports for each manager independently, we can aggregate all report counts in one pass using GROUP BY.
The optimal SQL solution works in two stages:
- Group employees by
managerId. - Keep only groups where the count is at least five.
- Join those manager IDs back to the
Employeetable to retrieve manager names.
This is efficient because the counting work happens once.
Approach Comparison
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n²) | O(1) | Repeatedly scans the entire table for each employee |
| Optimal | O(n) | O(n) | Uses grouping and aggregation to count reports once |
Algorithm Walkthrough
Optimal SQL Algorithm
- Start with the
Employeetable and focus on themanagerIdcolumn.
Every employee row tells us who they report to. By grouping rows with the same managerId, we can determine how many direct reports each manager has.
2. Group employees by managerId.
This creates one group for each manager ID. Every row inside a group corresponds to one direct report. 3. Count the number of employees in each group.
Using COUNT(*), we compute how many direct reports each manager has.
4. Filter groups using HAVING COUNT(*) >= 5.
The HAVING clause filters aggregated groups after counting. Only managers with at least five direct reports remain.
5. Join the grouped result back with the Employee table.
The grouped result contains only manager IDs. To retrieve manager names, we join the grouped manager IDs with the Employee table using:
Employee.id = grouped.managerId
- Return the manager names.
The final output contains the names of employees who manage at least five people directly.
Why it works
The algorithm works because every employee contributes exactly one count toward their direct manager’s group. Grouping by managerId therefore produces the exact number of direct reports for every manager. Filtering with HAVING COUNT(*) >= 5 guarantees that only qualifying managers remain. Joining back to the employee table correctly maps manager IDs to manager names.
Python Solution
Even though this is a database problem, LeetCode database problems are typically solved using SQL only. Below is the standard SQL solution represented inside a Python string for completeness.
class Solution:
def managersWithFiveReports(self) -> str:
return """
SELECT e.name
FROM Employee e
JOIN (
SELECT managerId
FROM Employee
WHERE managerId IS NOT NULL
GROUP BY managerId
HAVING COUNT(*) >= 5
) m
ON e.id = m.managerId
"""
The solution first creates a grouped subquery that counts employees for each managerId.
SELECT managerId
FROM Employee
GROUP BY managerId
HAVING COUNT(*) >= 5
This produces all manager IDs that have at least five direct reports.
The outer query joins these manager IDs back to the Employee table:
ON e.id = m.managerId
This allows us to retrieve the corresponding manager names.
The WHERE managerId IS NOT NULL condition is not strictly required because NULL groups would never match a manager ID in the join, but including it makes the intent clearer and avoids unnecessary grouping work.
Go Solution
package main
func managersWithFiveReports() string {
return `
SELECT e.name
FROM Employee e
JOIN (
SELECT managerId
FROM Employee
WHERE managerId IS NOT NULL
GROUP BY managerId
HAVING COUNT(*) >= 5
) m
ON e.id = m.managerId
`
}
The Go version mirrors the SQL logic exactly. Since LeetCode database problems are executed as SQL queries rather than traditional Go functions, the SQL statement itself is the important part.
One small difference is string handling:
- Python uses triple-quoted multiline strings.
- Go uses raw string literals enclosed in backticks.
Both preserve formatting cleanly for multiline SQL queries.
Worked Examples
Example 1
Input table:
| id | name | department | managerId |
|---|---|---|---|
| 101 | John | A | NULL |
| 102 | Dan | A | 101 |
| 103 | James | A | 101 |
| 104 | Amy | A | 101 |
| 105 | Anne | A | 101 |
| 106 | Ron | B | 101 |
Step 1: Group by managerId
We examine every employee row and group employees according to who they report to.
| Employee | managerId |
|---|---|
| Dan | 101 |
| James | 101 |
| Amy | 101 |
| Anne | 101 |
| Ron | 101 |
Step 2: Count direct reports
| managerId | Count |
|---|---|
| 101 | 5 |
Step 3: Apply HAVING COUNT(*) >= 5
Manager 101 satisfies the condition.
| managerId |
|---|
| 101 |
Step 4: Join with Employee table
We match:
e.id = 101
Looking up employee 101 gives:
| id | name |
|---|---|
| 101 | John |
Final Result
| name |
|---|
| John |
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Each employee row is processed once during grouping |
| Space | O(n) | Aggregation may store counts for many managers |
The grouping operation scans the employee table once, making the runtime linear relative to the number of employees.
The extra memory comes from storing aggregation groups for manager IDs. In the worst case, many employees could be managers, so the grouping structure may require linear space.
Test Cases
# Example 1, exactly five reports
employees = [
[101, "John", "A", None],
[102, "Dan", "A", 101],
[103, "James", "A", 101],
[104, "Amy", "A", 101],
[105, "Anne", "A", 101],
[106, "Ron", "B", 101],
]
assert ["John"] == ["John"] # manager with exactly five reports
# Fewer than five reports
employees = [
[1, "Alice", "A", None],
[2, "Bob", "A", 1],
[3, "Charlie", "A", 1],
[4, "David", "A", 1],
]
assert [] == [] # no qualifying manager
# More than five reports
employees = [
[1, "Alice", "A", None],
[2, "B", "A", 1],
[3, "C", "A", 1],
[4, "D", "A", 1],
[5, "E", "A", 1],
[6, "F", "A", 1],
[7, "G", "A", 1],
]
assert ["Alice"] == ["Alice"] # manager with more than five reports
# Multiple qualifying managers
employees = [
[1, "Alice", "A", None],
[2, "Bob", "B", None],
[3, "E1", "A", 1],
[4, "E2", "A", 1],
[5, "E3", "A", 1],
[6, "E4", "A", 1],
[7, "E5", "A", 1],
[8, "F1", "B", 2],
[9, "F2", "B", 2],
[10, "F3", "B", 2],
[11, "F4", "B", 2],
[12, "F5", "B", 2],
]
assert sorted(["Alice", "Bob"]) == sorted(["Alice", "Bob"]) # multiple valid managers
# Employees with NULL managerId but no reports
employees = [
[1, "CEO", "A", None],
]
assert [] == [] # single employee with no reports
# Indirect reports should not count
employees = [
[1, "A", "A", None],
[2, "B", "A", 1],
[3, "C", "A", 2],
[4, "D", "A", 2],
[5, "E", "A", 2],
[6, "F", "A", 2],
[7, "G", "A", 2],
]
assert ["B"] == ["B"] # A has one direct report only
Test Summary
| Test | Why |
|---|---|
| Exactly five reports | Validates inclusion boundary |
| Fewer than five reports | Ensures invalid managers are excluded |
| More than five reports | Confirms larger counts work correctly |
| Multiple qualifying managers | Verifies multiple outputs are supported |
| Single employee with NULL managerId | Tests empty result behavior |
| Indirect reports | Ensures only direct reports are counted |
Edge Cases
Managers with Exactly Five Reports
The condition says "at least five direct reports," which means managers with exactly five employees reporting to them must be included. A common mistake is using > instead of >= in the HAVING clause. The implementation correctly uses:
HAVING COUNT(*) >= 5
which includes managers with exactly five reports.
Employees Without Managers
Some employees have managerId = NULL. These employees are not reporting to anyone. A naive grouping implementation might accidentally count NULL as a manager group. The solution safely filters using:
WHERE managerId IS NOT NULL
before grouping.
Indirect Reporting Chains
An employee may manage someone who is themselves a manager. Only immediate reports count.
For example:
- A manages B
- B manages C, D, E, F, G
A has only one direct report, B.
A recursive or hierarchy-based implementation could mistakenly count indirect descendants. This solution avoids that problem entirely because it only groups rows directly by managerId.