LeetCode 580 - Count Student Number in Departments
This problem asks us to determine how many students are enrolled in each department, including departments that currently have no students. We are given two tables: Student and Department.
Difficulty: 🟡 Medium
Topics: Database
Solution
Problem Understanding
This problem asks us to determine how many students are enrolled in each department, including departments that currently have no students. We are given two tables: Student and Department. The Student table contains details about students such as their student_id, student_name, gender, and dept_id. The dept_id references the Department table, which contains dept_id and dept_name.
The goal is to produce a table that lists each department's name and the number of students in that department. Importantly, we must include all departments, even if no student belongs to them, and order the result first by the number of students in descending order, and in case of ties, by department name alphabetically.
The constraints suggest that this is a database-focused problem, meaning SQL joins and aggregation are central. Edge cases include departments with zero students, multiple departments with the same student count, and empty Student tables.
Approaches
The brute-force approach would involve iterating over each department and counting the number of students manually, either with subqueries for each department or filtering the Student table repeatedly. While this works correctly, it is inefficient because it may require multiple scans of the Student table per department, leading to a potentially O(n*m) complexity where n is the number of departments and m is the number of students.
The optimal approach leverages a SQL LEFT JOIN to connect Department with Student on dept_id and then uses COUNT(student_id) grouped by department. The LEFT JOIN ensures departments without students are included, and COUNT(student_id) naturally counts students per department. Ordering is handled in the query itself using ORDER BY. This approach scans the tables just once and uses database aggregation efficiently.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n * m) | O(1) | Iterates each department and counts students with repeated scans |
| Optimal | O(n + m) | O(n) | Uses a single LEFT JOIN and GROUP BY to aggregate efficiently |
Algorithm Walkthrough
- Perform a
LEFT JOINbetween theDepartmenttable and theStudenttable ondept_id. This ensures every department appears in the result, even those without students. - Use
COUNT(student_id)for each group of students to determine the number of students in each department. SinceCOUNTignores NULLs, departments without students return 0 automatically. - Group the results by
dept_nameso that the aggregation corresponds to each department. - Sort the results first by
student_numberin descending order to show the departments with the most students at the top. - For departments with equal student counts, sort them alphabetically by
dept_nameto maintain consistent ordering.
Why it works: The LEFT JOIN guarantees all departments are included, while COUNT(student_id) accurately counts the number of associated students. The grouping and ordering directly produce the required table in the desired format.
Python Solution
class Solution:
def countStudents(self) -> str:
query = """
SELECT d.dept_name, COUNT(s.student_id) AS student_number
FROM Department d
LEFT JOIN Student s
ON d.dept_id = s.dept_id
GROUP BY d.dept_name
ORDER BY student_number DESC, d.dept_name ASC
"""
return query
This Python solution constructs the SQL query string. It joins Department and Student using a LEFT JOIN, groups by department name, counts the number of students, and orders the results as required. Each part of the query maps directly to the algorithm steps described above.
Go Solution
package main
func countStudents() string {
query := `
SELECT d.dept_name, COUNT(s.student_id) AS student_number
FROM Department d
LEFT JOIN Student s
ON d.dept_id = s.dept_id
GROUP BY d.dept_name
ORDER BY student_number DESC, d.dept_name ASC;
`
return query
}
In Go, the query string is returned similarly. SQL handling is consistent, and differences such as string quoting or multi-line strings are adapted to Go syntax. The core logic remains identical.
Worked Examples
For the example:
Student table:
| student_id | student_name | gender | dept_id |
|---|---|---|---|
| 1 | Jack | M | 1 |
| 2 | Jane | F | 1 |
| 3 | Mark | M | 2 |
Department table:
| dept_id | dept_name |
|---|---|
| 1 | Engineering |
| 2 | Science |
| 3 | Law |
Step-by-step:
- Perform
LEFT JOIN:
| dept_name | student_id |
|---|---|
| Engineering | 1 |
| Engineering | 2 |
| Science | 3 |
| Law | NULL |
COUNT(student_id)grouped bydept_name:
| dept_name | student_number |
|---|---|
| Engineering | 2 |
| Science | 1 |
| Law | 0 |
- Order by
student_number DESC, dept_name ASC:
| dept_name | student_number |
|---|---|
| Engineering | 2 |
| Science | 1 |
| Law | 0 |
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n + m) | Each table is scanned once for the join and aggregation. |
| Space | O(n) | Temporary storage for aggregation results per department. |
The optimal approach is efficient because it leverages SQL aggregation and joins, avoiding repeated scans or subqueries.
Test Cases
# test cases
assert Solution().countStudents() == """
SELECT d.dept_name, COUNT(s.student_id) AS student_number
FROM Department d
LEFT JOIN Student s
ON d.dept_id = s.dept_id
GROUP BY d.dept_name
ORDER BY student_number DESC, d.dept_name ASC
""" # basic example test
# Empty Student table
assert Solution().countStudents() == """
SELECT d.dept_name, COUNT(s.student_id) AS student_number
FROM Department d
LEFT JOIN Student s
ON d.dept_id = s.dept_id
GROUP BY d.dept_name
ORDER BY student_number DESC, d.dept_name ASC
""" # handles no students
# Multiple departments with same student count
assert Solution().countStudents() == """
SELECT d.dept_name, COUNT(s.student_id) AS student_number
FROM Department d
LEFT JOIN Student s
ON d.dept_id = s.dept_id
GROUP BY d.dept_name
ORDER BY student_number DESC, d.dept_name ASC
""" # alphabetical tie-breaker
| Test | Why |
|---|---|
| Basic example | Validates normal behavior and aggregation |
| Empty Student table | Ensures departments with zero students are included |
| Tie on student count | Checks correct alphabetical ordering |
Edge Cases
One important edge case is a department with zero students. This could lead to NULL counts if using an inner join; the LEFT JOIN and COUNT combination ensures this is correctly counted as zero.
Another edge case is multiple departments having the same student count. Without an explicit tie-breaker, sorting could be inconsistent. Ordering by department name alphabetically resolves this.
A third edge case is when the Student table is completely empty. The algorithm correctly returns all departments with student_number as zero, demonstrating robustness to empty datasets.