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.
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.
We'll break down the solution step by step:
manager_id → [list of subordinate ids]
.headID
(the root of the tree).informTime
to the current time before passing it to their subordinates.We use a hash map (dictionary) to store the tree because lookups and insertions are O(1), which keeps our traversal efficient.
Let's walk through an example:
n = 6 headID = 2 manager = [2, 2, -1, 2, 2, 2] informTime = [0, 0, 1, 0, 0, 0]
The process:
Brute-force:
This is efficient and suitable for large input sizes.
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);
};
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.