Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1376. Time Needed to Inform All Employees - Leetcode Solution

Problem Description

You are given a company structure with n employees, each identified by a unique ID from 0 to n - 1. The company's head has the ID headID. Every employee except the head has exactly one direct manager, described by the array manager, where manager[i] is the direct manager of employee i. The head has manager[headID] = -1.

Each employee needs a certain amount of time to inform all their direct subordinates of urgent news. This is given in the array informTime, where informTime[i] is the time it takes for employee i to inform all their direct subordinates.

The task is to determine the minimum time needed for the head to inform all employees in the company. Assume information is spread in parallel: once a manager informs a subordinate, that subordinate can immediately begin informing their own subordinates.

  • There is exactly one head.
  • All employees are reachable from the head (the company is a tree structure).
  • Each employee is informed only once.

Thought Process

At first glance, this problem resembles traversing a tree, where each node (employee) can inform its children (subordinates) after a certain delay. A brute-force approach might be to simulate the process for each employee, but this would be inefficient for large companies.

The main challenge is to identify the longest path from the head to any leaf (employee with no subordinates), since information can be spread in parallel down different branches. The total time is determined by the slowest branch, not the sum of all times.

To optimize, we can model the company as a tree and use a tree traversal (like DFS or BFS) to compute, for each path, the cumulative time taken to reach each employee. We then find the maximum among these times.

Solution Approach

We'll break down the solution step by step:

  1. Build the Company Tree:
    • For each employee, add them as a child (subordinate) to their manager in a mapping: manager_id → [list of subordinate ids].
    • This allows us to quickly find all subordinates for any given manager.
  2. Traverse the Tree:
    • Start from the headID (the root of the tree).
    • Use Depth-First Search (DFS) to recursively visit each subordinate, keeping track of the time taken so far.
    • At each employee, add their informTime to the current time before passing it to their subordinates.
  3. Compute the Maximum Time:
    • For each path from the head to a leaf, record the total accumulated time.
    • The answer is the maximum of all these times, representing the slowest path for the information to reach all employees.

We use a hash map (dictionary) to store the tree because lookups and insertions are O(1), which keeps our traversal efficient.

Example Walkthrough

Let's walk through an example:

    n = 6
    headID = 2
    manager = [2, 2, -1, 2, 2, 2]
    informTime = [0, 0, 1, 0, 0, 0]
  
  • Employee 2 is the head. All others (0, 1, 3, 4, 5) report to 2.
  • Employee 2 takes 1 minute to inform all subordinates.
  • Employees 0, 1, 3, 4, 5 take 0 minutes (no subordinates).

The process:

  • At time 0: Head (2) starts informing subordinates.
  • At time 1: All subordinates (0, 1, 3, 4, 5) are informed (since 2's informTime=1).
  • None of these subordinates have further subordinates, so process ends.
Total time: 1 minute

Time and Space Complexity

Brute-force:

  • Simulating the process for all employees without building a tree might require O(n^2) time in the worst case, as we might revisit employees multiple times.
Optimized Approach:
  • Building the tree: O(n) time and space, as we process each employee once.
  • DFS traversal: O(n) time, visiting each employee exactly once.
  • Total: O(n) time and O(n) space.

This is efficient and suitable for large input sizes.

Code Implementation

class Solution:
    def numOfMinutes(self, n, headID, manager, informTime):
        from collections import defaultdict

        tree = defaultdict(list)
        for emp, mgr in enumerate(manager):
            if mgr != -1:
                tree[mgr].append(emp)

        def dfs(emp):
            if not tree[emp]:
                return 0
            return informTime[emp] + max(dfs(sub) for sub in tree[emp])

        return dfs(headID)
      
class Solution {
public:
    int numOfMinutes(int n, int headID, vector<int>& manager, vector<int>& informTime) {
        vector<vector<int>> tree(n);
        for (int i = 0; i < n; ++i) {
            if (manager[i] != -1)
                tree[manager[i]].push_back(i);
        }
        return dfs(headID, tree, informTime);
    }
    
    int dfs(int emp, vector<vector<int>>& tree, vector<int>& informTime) {
        if (tree[emp].empty())
            return 0;
        int maxTime = 0;
        for (int sub : tree[emp]) {
            maxTime = max(maxTime, dfs(sub, tree, informTime));
        }
        return informTime[emp] + maxTime;
    }
};
      
class Solution {
    public int numOfMinutes(int n, int headID, int[] manager, int[] informTime) {
        List<List<Integer>> tree = new ArrayList<>();
        for (int i = 0; i < n; i++) tree.add(new ArrayList<>());
        for (int i = 0; i < n; i++) {
            if (manager[i] != -1)
                tree.get(manager[i]).add(i);
        }
        return dfs(headID, tree, informTime);
    }
    private int dfs(int emp, List<List<Integer>> tree, int[] informTime) {
        if (tree.get(emp).isEmpty()) return 0;
        int maxTime = 0;
        for (int sub : tree.get(emp)) {
            maxTime = Math.max(maxTime, dfs(sub, tree, informTime));
        }
        return informTime[emp] + maxTime;
    }
}
      
var numOfMinutes = function(n, headID, manager, informTime) {
    const tree = Array.from({length: n}, () => []);
    for (let i = 0; i < n; ++i) {
        if (manager[i] !== -1)
            tree[manager[i]].push(i);
    }
    function dfs(emp) {
        if (tree[emp].length === 0) return 0;
        let maxTime = 0;
        for (let sub of tree[emp]) {
            maxTime = Math.max(maxTime, dfs(sub));
        }
        return informTime[emp] + maxTime;
    }
    return dfs(headID);
};
      

Summary

This problem is a classic example of tree traversal where the goal is to find the longest path from the root to any leaf, with edge weights (inform times). By modeling the company as a tree and using a simple DFS, we efficiently compute the minimum time needed to inform all employees. The key insight is that, due to parallel information spread, only the slowest branch determines the total time. This approach is both intuitive and highly efficient.