Problem: 690. 员工的重要性
思路
这个问题可以视作一个典型的图遍历问题。每个员工可以看作图中的一个节点,而员工之间的上下级关系可以看作节点之间的有向边。需要从给定的员工 ID 开始,遍历该员工以及其所有下属节点,计算这些节点的重要度总和。
要解决这个问题,可以选择以下两种常见的图遍历方法之一:
- 深度优先搜索 (DFS):使用递归或显式栈来遍历图。
- 广度优先搜索 (BFS):使用队列来逐层遍历图。
在这道题目中,采用 DFS 或 BFS 都可以解决问题。这里将采用 DFS 来解决。
解题过程
1.数据结构优化
-
首先,需要将给定的员工列表转换为一个便于访问的数据结构。将每个员工对象存储在一个数组中,并通过其 ID 作为索引进行直接访问,使后续查找员工的时间复杂度为 O(1)。
-
通过遍历
employees列表,找出maxId,以此来初始化大小合适的数组employeeArray,确保了输入数据不连续,也能够正确处理。
2.使用栈进行深度优先搜索
-
选择用栈来进行深度优先搜索(DFS),这是一个非递归的方法,避免了递归调用可能带来的栈溢出风险。
-
初始化时,将目标员工的 ID 压入栈中,然后进入循环,直到栈为空为止。
-
每次从栈中弹出一个员工,计算其重要度,并将其所有下属的 ID 压入栈中。
-
这种方法可以确保遍历到所有下属,并累加其重要度。
3.使用 Span 优化栈
-
使用
Span<int>来分配栈的空间,避免了堆上分配内存的开销,并减少了 GC(垃圾回收)的频率。 -
stackalloc在栈上分配内存,比普通数组分配更高效,但需要注意栈空间的限制。
4.计算总重要度
- 每次弹出栈时,累加当前员工的重要度到
totalImportance中,直到遍历完所有相关员工。
复杂度
- 时间复杂度: O(n)
- 空间复杂度: O(n)
Code
internal class Solution
{
public int GetImportance(IList<Employee> employees, int id)
{
int maxId = 0;
for (int i = 0; i < employees.Count; i++)
{
if (employees[i].id > maxId)
maxId = employees[i].id;
}
Employee[] employeeArray = new Employee[maxId + 1];
for (int i = 0; i < employees.Count; i++)
{
var emp = employees[i];
employeeArray[emp.id] = emp;
}
int totalImportance = 0;
Span<int> stack = stackalloc int[employees.Count];
int stackPointer = 0;
stack[stackPointer++] = id;
while (stackPointer > 0)
{
int empId = stack[--stackPointer];
var employee = employeeArray[empId];
totalImportance += employee.importance;
var subs = employee.subordinates;
for (int i = 0; i < subs.Count; i++)
{
stack[stackPointer++] = subs[i];
}
}
return totalImportance;
}
}
2507





