690. Employee Importance
Problem Description
You are given information about employees in a company, where each employee has:
- A unique ID number
- An importance value (representing their contribution to the company)
- A list of IDs representing their direct subordinates (employees who report directly to them)
The employee data is provided as an array of Employee
objects, where each object contains:
employees[i].id
- the unique identifier for the i-th employeeemployees[i].importance
- the importance value for the i-th employeeemployees[i].subordinates
- a list containing the IDs of all employees who directly report to the i-th employee
Your task is to calculate the total importance value for a given employee, which includes:
- The employee's own importance value
- The importance values of all their direct subordinates
- The importance values of all their indirect subordinates (subordinates of subordinates, and so on)
Given an employee ID, you need to return the sum of importance values for that employee and their entire reporting hierarchy beneath them.
For example, if Employee A has importance 5 and has two subordinates:
- Employee B with importance 3 (who has no subordinates)
- Employee C with importance 4 (who has Employee D as a subordinate with importance 2)
Then the total importance for Employee A would be: 5 + 3 + 4 + 2 = 14
Flowchart Walkthrough
First, let's pin down the algorithm using the Flowchart. Here's a step-by-step walkthrough:
Is it a graph?
- Yes: The employee structure forms a graph where each employee is a node and the subordinate relationships are edges. Specifically, it's a hierarchical structure where employees point to their subordinates.
Is it a tree?
- Yes: The employee hierarchy is actually a tree structure. Each employee (except the root/top-level employees) has exactly one manager (parent), and there are no cycles in the reporting structure. The subordinate relationships form a tree where we can traverse from any employee down through their reporting chain.
DFS
- Since we identified this as a tree structure, the flowchart leads us directly to DFS (Depth-First Search) as the appropriate algorithm.
Conclusion: The flowchart suggests using DFS for this problem. This makes perfect sense because:
- We need to traverse the entire subtree rooted at the given employee
- We need to aggregate values (importance) from all nodes in the subtree
- DFS naturally handles the recursive nature of exploring each employee and all their subordinates (direct and indirect)
The DFS approach will:
- Start at the given employee ID
- Add that employee's importance value
- Recursively visit all subordinates and add their importance values
- Continue this process for all levels of the hierarchy until all subordinates are accounted for
Intuition
When we look at this problem, we need to find the total importance of an employee and all their subordinates (both direct and indirect). This immediately suggests we need to traverse through a hierarchical structure.
Think of the company structure like a family tree - each employee can have multiple "children" (subordinates), and those subordinates can have their own subordinates, and so on. To get the total importance, we need to visit every person in this specific branch of the tree.
The key insight is that this is a recursive problem: the total importance of any employee equals their own importance plus the sum of the total importance of each of their direct subordinates. This naturally breaks down into smaller subproblems of the same type.
Why DFS works perfectly here:
- We start with one employee and need to explore their entire "subtree" completely
- For each subordinate we encounter, we need to fully explore their subordinates before moving to the next sibling
- We're aggregating values as we traverse - each recursive call returns the importance sum for that subtree
The challenge is efficiently accessing employee data by ID. Since we need to look up employees by their ID repeatedly (when we encounter subordinate IDs), we first create a hash table d
that maps each employee ID to their Employee object. This gives us O(1) lookup time.
The recursive DFS function then becomes straightforward:
- Base case: An employee with no subordinates returns just their own importance
- Recursive case: Return the employee's importance plus the sum of DFS calls on all their subordinates
This approach ensures we visit each employee exactly once and correctly accumulate all importance values in the hierarchy.
Learn more about Tree, Depth-First Search and Breadth-First Search patterns.
Solution Approach
The solution uses a Hash Table + DFS approach to efficiently calculate the total importance value.
Step 1: Build a Hash Table for Quick Lookup
First, we create a dictionary d
that maps each employee's ID to their Employee object:
d = {e.id: e for e in employees}
This preprocessing step allows us to quickly access any employee's information by their ID in O(1) time, which is crucial since we'll need to look up subordinates repeatedly during traversal.
Step 2: Implement DFS Function
We define a recursive DFS function that calculates the total importance for an employee and all their subordinates:
def dfs(i: int) -> int:
return d[i].importance + sum(dfs(j) for j in d[i].subordinates)
This function works as follows:
- Takes an employee ID
i
as input - Returns the employee's own importance value:
d[i].importance
- Plus the sum of importance values from all subordinates:
sum(dfs(j) for j in d[i].subordinates)
- The
sum()
function with a generator expression recursively callsdfs()
for each subordinate ID
Step 3: Start DFS from Target Employee
Finally, we initiate the DFS traversal from the given employee ID:
return dfs(id)
How the Recursion Works:
For each employee, the function:
- Adds their importance value to the result
- Recursively processes each subordinate in their list
- The recursion naturally handles all levels of the hierarchy
- When an employee has no subordinates (empty list), the
sum()
returns 0, serving as the base case
Time Complexity: O(n) where n is the total number of employees, as we visit each employee exactly once.
Space Complexity: O(n) for the hash table storage, plus O(h) for the recursion stack where h is the height of the employee hierarchy tree.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate how the solution works.
Given Employee Data:
Employee 1: importance = 5, subordinates = [2, 3] Employee 2: importance = 3, subordinates = [] Employee 3: importance = 3, subordinates = [4] Employee 4: importance = 1, subordinates = []
Target: Calculate total importance for Employee ID = 1
Step 1: Build Hash Table
d = {
1: Employee(id=1, importance=5, subordinates=[2,3]),
2: Employee(id=2, importance=3, subordinates=[]),
3: Employee(id=3, importance=3, subordinates=[4]),
4: Employee(id=4, importance=1, subordinates=[])
}
Step 2: Execute DFS Traversal
Starting with dfs(1)
:
dfs(1): → d[1].importance = 5 → sum(dfs(j) for j in [2, 3]) dfs(2): → d[2].importance = 3 → sum(dfs(j) for j in []) // empty list → returns: 3 + 0 = 3 dfs(3): → d[3].importance = 3 → sum(dfs(j) for j in [4]) dfs(4): → d[4].importance = 1 → sum(dfs(j) for j in []) // empty list → returns: 1 + 0 = 1 → returns: 3 + 1 = 4 → returns: 5 + (3 + 4) = 12
Visual Representation of the Traversal:
Employee 1 (importance: 5) / \ Employee 2 Employee 3 (importance: 3) (importance: 3) | Employee 4 (importance: 1) Total: 5 + 3 + 3 + 1 = 12
The DFS traversal visits nodes in this order: 1 → 2 → 3 → 4, accumulating importance values as it returns from each recursive call. Each employee's total contribution includes their own importance plus the sum returned by all their subordinates' recursive calls.
Solution Implementation
1"""
2# Definition for Employee.
3class Employee:
4 def __init__(self, id: int, importance: int, subordinates: List[int]):
5 self.id = id
6 self.importance = importance
7 self.subordinates = subordinates
8"""
9
10from typing import List
11
12
13class Solution:
14 def getImportance(self, employees: List["Employee"], id: int) -> int:
15 """
16 Calculate the total importance value of an employee and all their subordinates.
17
18 Args:
19 employees: List of Employee objects
20 id: The ID of the employee whose total importance needs to be calculated
21
22 Returns:
23 Total importance value of the employee and all subordinates
24 """
25
26 def calculate_total_importance(employee_id: int) -> int:
27 """
28 Recursively calculate importance for an employee and their subordinates.
29
30 Args:
31 employee_id: The ID of the current employee
32
33 Returns:
34 Total importance including the employee and all subordinates
35 """
36 # Get the employee object from the map
37 employee = employee_map[employee_id]
38
39 # Calculate total: employee's importance + sum of all subordinates' importance
40 subordinates_importance = sum(
41 calculate_total_importance(subordinate_id)
42 for subordinate_id in employee.subordinates
43 )
44
45 return employee.importance + subordinates_importance
46
47 # Create a map for O(1) employee lookup by ID
48 employee_map = {employee.id: employee for employee in employees}
49
50 # Start DFS from the given employee ID
51 return calculate_total_importance(id)
52
1/*
2// Definition for Employee.
3class Employee {
4 public int id;
5 public int importance;
6 public List<Integer> subordinates;
7};
8*/
9
10class Solution {
11 // HashMap to store employee ID to Employee object mapping for O(1) lookup
12 private final Map<Integer, Employee> employeeMap = new HashMap<>();
13
14 /**
15 * Calculates the total importance value of an employee and all their subordinates.
16 *
17 * @param employees List of all employees in the organization
18 * @param id The ID of the employee whose total importance needs to be calculated
19 * @return The sum of importance values for the employee and all subordinates
20 */
21 public int getImportance(List<Employee> employees, int id) {
22 // Build a map for quick employee lookup by ID
23 for (Employee employee : employees) {
24 employeeMap.put(employee.id, employee);
25 }
26
27 // Perform depth-first search starting from the target employee
28 return calculateTotalImportance(id);
29 }
30
31 /**
32 * Recursively calculates the importance sum using depth-first search.
33 *
34 * @param employeeId The ID of the current employee being processed
35 * @return The total importance value including this employee and all subordinates
36 */
37 private int calculateTotalImportance(int employeeId) {
38 // Get the employee object from the map
39 Employee currentEmployee = employeeMap.get(employeeId);
40
41 // Initialize sum with current employee's importance
42 int totalImportance = currentEmployee.importance;
43
44 // Recursively add importance of all subordinates
45 for (int subordinateId : currentEmployee.subordinates) {
46 totalImportance += calculateTotalImportance(subordinateId);
47 }
48
49 return totalImportance;
50 }
51}
52
1/*
2// Definition for Employee.
3class Employee {
4public:
5 int id;
6 int importance;
7 vector<int> subordinates;
8};
9*/
10
11class Solution {
12public:
13 int getImportance(vector<Employee*> employees, int id) {
14 // Build a hash map for O(1) employee lookup by ID
15 unordered_map<int, Employee*> employeeMap;
16 for (auto& employee : employees) {
17 employeeMap[employee->id] = employee;
18 }
19
20 // Define recursive DFS function to calculate total importance
21 function<int(int)> calculateTotalImportance = [&](int employeeId) -> int {
22 // Start with current employee's importance value
23 int totalImportance = employeeMap[employeeId]->importance;
24
25 // Recursively add importance of all subordinates
26 for (int subordinateId : employeeMap[employeeId]->subordinates) {
27 totalImportance += calculateTotalImportance(subordinateId);
28 }
29
30 return totalImportance;
31 };
32
33 // Start DFS from the given employee ID
34 return calculateTotalImportance(id);
35 }
36};
37
1/**
2 * Definition for Employee.
3 * class Employee {
4 * id: number
5 * importance: number
6 * subordinates: number[]
7 * constructor(id: number, importance: number, subordinates: number[]) {
8 * this.id = (id === undefined) ? 0 : id;
9 * this.importance = (importance === undefined) ? 0 : importance;
10 * this.subordinates = (subordinates === undefined) ? [] : subordinates;
11 * }
12 * }
13 */
14
15/**
16 * Calculates the total importance value of an employee and all their subordinates
17 * @param employees - Array of all employees in the organization
18 * @param id - The ID of the employee whose total importance needs to be calculated
19 * @returns The sum of importance values for the employee and all subordinates
20 */
21function getImportance(employees: Employee[], id: number): number {
22 // Create a map for O(1) employee lookup by ID
23 const employeeMap = new Map<number, Employee>();
24
25 // Populate the map with all employees
26 for (const employee of employees) {
27 employeeMap.set(employee.id, employee);
28 }
29
30 /**
31 * Depth-first search to calculate total importance
32 * @param employeeId - Current employee ID being processed
33 * @returns Total importance of the employee and all subordinates
34 */
35 const calculateTotalImportance = (employeeId: number): number => {
36 // Get the current employee from the map
37 const currentEmployee = employeeMap.get(employeeId)!;
38
39 // Start with the current employee's importance value
40 let totalImportance = currentEmployee.importance;
41
42 // Recursively add importance of all subordinates
43 for (const subordinateId of currentEmployee.subordinates) {
44 totalImportance += calculateTotalImportance(subordinateId);
45 }
46
47 return totalImportance;
48 };
49
50 // Start DFS from the given employee ID
51 return calculateTotalImportance(id);
52}
53
Time and Space Complexity
Time Complexity: O(n)
The algorithm first creates a dictionary mapping employee IDs to employee objects, which takes O(n)
time where n
is the number of employees. Then it performs a depth-first search (DFS) starting from the given employee ID. During the DFS traversal, each employee node is visited exactly once. For each employee visited, we access their importance value and iterate through their subordinates list. Since each employee appears exactly once in the organizational hierarchy (it's a tree structure), the total number of operations across all recursive calls is proportional to the number of employees. Therefore, the overall time complexity is O(n)
.
Space Complexity: O(n)
The space complexity consists of two main components:
- The dictionary
d
that stores the mapping from employee IDs to employee objects requiresO(n)
space to store alln
employees. - The recursive DFS call stack can go as deep as the height of the employee hierarchy tree. In the worst case (a completely linear hierarchy where each employee has at most one subordinate), the recursion depth could be
O(n)
.
Therefore, the total space complexity is O(n)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Circular Dependencies in Employee Hierarchy
One critical pitfall that's often overlooked is the possibility of circular references in the employee hierarchy. If the input data contains a cycle (e.g., Employee A reports to B, B reports to C, and C reports back to A), the recursive DFS will enter an infinite loop, causing a stack overflow error.
Example of problematic data:
# Employee 1 has subordinate 2 # Employee 2 has subordinate 3 # Employee 3 has subordinate 1 (creates a cycle!)
Solution: Add a visited set to track processed employees and prevent revisiting them:
class Solution:
def getImportance(self, employees: List["Employee"], id: int) -> int:
# Create employee map
employee_map = {employee.id: employee for employee in employees}
# Track visited employees to detect cycles
visited = set()
def calculate_total_importance(employee_id: int) -> int:
# Check if we've already processed this employee (cycle detection)
if employee_id in visited:
return 0
# Mark employee as visited
visited.add(employee_id)
# Get the employee object
employee = employee_map[employee_id]
# Calculate total importance
subordinates_importance = sum(
calculate_total_importance(subordinate_id)
for subordinate_id in employee.subordinates
)
return employee.importance + subordinates_importance
return calculate_total_importance(id)
2. Invalid Employee IDs in Subordinates List
Another common issue is when a subordinate ID in the list doesn't correspond to any employee in the input data. This would cause a KeyError
when trying to access employee_map[subordinate_id]
.
Solution: Add error handling or validation:
def calculate_total_importance(employee_id: int) -> int:
# Validate employee ID exists
if employee_id not in employee_map:
return 0 # or raise ValueError(f"Employee {employee_id} not found")
employee = employee_map[employee_id]
subordinates_importance = sum(
calculate_total_importance(subordinate_id)
for subordinate_id in employee.subordinates
if subordinate_id in employee_map # Skip invalid IDs
)
return employee.importance + subordinates_importance
3. Missing Initial Employee ID
The given id
parameter might not exist in the employees list, causing an immediate KeyError
.
Solution: Validate the input before processing:
class Solution:
def getImportance(self, employees: List["Employee"], id: int) -> int:
employee_map = {employee.id: employee for employee in employees}
# Validate the target employee exists
if id not in employee_map:
return 0 # or raise ValueError(f"Employee {id} not found")
# Continue with DFS...
These defensive programming practices make the solution more robust against malformed or unexpected input data.
What's the relationship between a tree and a graph?
Recommended Readings
Everything About Trees A tree is a type of graph data structure composed of nodes and edges Its main properties are It is acyclic doesn't contain any cycles There exists a path from the root to any node Has N 1 edges where N is the number of nodes in the tree and
https assets algo monster cover_photos dfs svg Depth First Search Prereqs Recursion Review problems recursion_intro Trees problems tree_intro With a solid understanding of recursion under our belts we are now ready to tackle one of the most useful techniques in coding interviews Depth First Search DFS As the name suggests
https assets algo monster cover_photos bfs svg Breadth First Search on Trees Hopefully by this time you've drunk enough DFS Kool Aid to understand its immense power and seen enough visualization to create a call stack in your mind Now let me introduce the companion spell Breadth First Search BFS
Want a Structured Path to Master System Design Too? Don’t Miss This!