. - 力扣(LeetCode)
力扣-207题
要判定一个图是否为有向无环图(DAG, Directed Acyclic Graph),可以使用拓扑排序(Topological Sort)的方法。如果一个有向图存在拓扑排序,那么它就是一个DAG。
解决思路:拓扑排序
- 构建入度数组:首先构建每个节点的入度数组。
- 初始化队列:将所有入度为0的节点加入队列,这些节点可以作为拓扑排序的起始点。
- 拓扑排序:从队列中逐个取出节点,将其邻接节点的入度减1,如果某个邻接节点的入度变为0,则将其加入队列。
- 检查是否完成:最终检查是否所有节点都被处理过,如果是则说明可以完成所有课程,否则不能。
public static boolean canFinish(int numCourses, int[][] prerequisites) {
int[] inDegree = new int[numCourses];
List<List<Integer>> adjList = new ArrayList<>(); // 邻接表
// 初始化邻接表
for (int i = 0; i < numCourses; i++) {
adjList.add(new ArrayList<>());
}
// 构建图和入度数组
for (int[] prerequisite : prerequisites) {
int dest = prerequisite[0];
int src = prerequisite[1];
adjList.get(src).add(dest); // 构建邻接表
inDegree[dest]++; // 计算入度
}
// 将所有入度为0的节点加入队列
LinkedList<Integer> list = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (inDegree[i] == 0) {
list.add(i);
}
}
int re = 0; // 记录已经处理过的节点数
while (!list.isEmpty()) {
re++;
Integer current = list.poll();
// 遍历当前节点的所有邻接节点
for (int neighbor : adjList.get(current)) {
inDegree[neighbor]--; // 邻接节点入度减1
if (inDegree[neighbor] == 0) {
list.add(neighbor); // 如果入度为0,加入队列
}
}
}
// 如果所有课程都被处理过,则可以完成所有课程
return re == numCourses;
}