LeetCode 690. 员工的重要性
题目描述




题意分析
每名员工给出唯一编号、重要度和直属下属编号,需要求指定员工本人,以及他的所有直接、间接下属的重要度总和。
输入列表的顺序不代表上下级关系,编号也不等于列表下标。应先按编号建立索引,再从目标员工沿下属关系访问,避免遗漏深层下属或加入无关员工。
解法:哈希表 + DFS
核心思路
[!blue]
先建立
empMap[id] = employee,将下属列表里的编号转换为可以直接取得的员工对象。这样每次递归无需重新扫描整个员工列表。定义
dfs(id)返回编号为id的员工及其全部下属的重要度之和。先取出员工,把total初始化为他本人的重要度,再对每个直属下属递归调用dfs,将返回的整棵下属子树贡献累加进来。没有直属下属的员工无需继续递归,循环为空,直接返回自身重要度。对于有下属的员工,题目给定的上下级结构中,每名员工至多有一个直属上级,各直属下属分支不会重复包含同一个人;这些分支加上员工本人恰好覆盖所求范围。因此只要子调用返回正确的子树总和,当前调用的结果也正确。
遍历从指定员工开始,所以组织中其他分支不会进入求和。重要度允许为负,但题目要求完整累计这一层级的所有人,不能因为某个值为负就剪掉该分支。
解题步骤
- 遍历全部员工,以员工编号作为键建立映射。
- 从目标编号调用递归函数,查出对应员工对象。
- 先计入本人重要度,再递归累计每个直属下属的完整贡献。
- 返回当前总和,最外层的返回值就是目标员工及全部下属的重要度。
代码实现
class Solution {
private final Map<Integer, Employee> empMap = new HashMap<>();
public int getImportance(List<Employee> employees, int id) {
for (Employee emp : employees) {
empMap.put(emp.id, emp);
}
return dfs690(id);
}
private int dfs690(int id) {
Employee emp = empMap.get(id);
// 先计入本人,再累加每名直属下属的完整子树贡献。
int total = emp.importance;
for (int subId : emp.subordinates) {
total += dfs690(subId);
}
return total;
}
}
func getImportance(employees []*Employee, id int) int {
empMap := make(map[int]*Employee, len(employees))
for _, emp := range employees {
empMap[emp.Id] = emp
}
var dfs func(cur int) int
dfs = func(cur int) int {
emp := empMap[cur]
// 先计入本人,再累加每名直属下属的完整子树贡献。
total := emp.Importance
for _, subId := range emp.Subordinates {
total += dfs(subId)
}
return total
}
return dfs(id)
}
复杂度分析
设员工总数为
n,目标子树包含m名员工,高度为h。
- 时间复杂度:期望 $O(n+m)$。建立映射扫描全部员工,递归对目标范围内每个人访问一次;由于
m <= n,可以写为 $O(n)$。- 空间复杂度:Go 本次映射和递归栈为 $O(n+h)$。Java 的成员映射在同一实例中保留已有记录,若累计保存的不同编号数为
U,则为 $O(U+h)$;单次新实例调用时U = n。
关键点总结
[!green]
- 编号映射只负责快速查人,真正的遍历方向由直属下属列表决定。
- 递归函数返回完整子树总和,父节点无需了解更深层的具体结构。
- 本人与各直属下属分支构成所求人员范围,逐项累加即可。
- 重要度的正负不影响是否访问,所有目标下属都必须计入。
易错点总结
[!yellow]
- 把员工编号直接当列表下标,可能取错对象或越界。
- 只累加直属下属的字段,遗漏更深层的间接下属。
- 把全部员工都加入答案,会把目标层级以外的人也算进去。
- 递归只累加下属而忘记当前员工,会漏掉本人贡献。
- 发现负重要度就停止递归,会遗漏题目要求纳入的人员及其下属。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 582. 杀掉进程 | 中等 | 同样按ID到子节点列表遍历全部后代,原题收集进程ID,本题累加每个员工的重要度。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!