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…

LeetCode Problem 570

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 101 manages employees 102, 103, 104, 105, and 106, then employee 101 has five direct reports.
  • If employee 102 manages additional people underneath them, those employees do not count toward employee 101’s total.

The expected output is a table containing only the names of managers who satisfy the condition.

The input guarantees several important properties:

  • id is unique.
  • managerId references another employee’s id, or is NULL.
  • 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 NULL as managerId may 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:

  1. Scan the entire table.
  2. Count rows where managerId == current_employee.id.
  3. 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:

  1. Group employees by managerId.
  2. Keep only groups where the count is at least five.
  3. Join those manager IDs back to the Employee table 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

  1. Start with the Employee table and focus on the managerId column.

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
  1. 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.