力扣labuladong一刷day44天环检测与拓扑排序
一、207. 课程表
题目链接:https://leetcode.cn/problems/course-schedule/
思路:简单来说就是判断有向图是否有环,如果有环就无法完成课程。要遍历图首先构建邻接表,即buildGraph,然后进行遍历,采用深度优先遍历,需要借助一个标记数组,来到过当前节点即标记,这就解决了遍历问题了。其次是解决是否有环的问题,可以借助回溯的思想,进入节点进行标记,离开节点取消标记,没有环是正常的,可以随着遍历走遍全树,如果当前节点被标记则说明有环,因为还没有回溯离开把节点标记取消,就遇到了,说明有环。
class Solution {
boolean[] visited;
boolean[] onPaths;
boolean hasCycle;
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] graph = buildGraph(numCourses, prerequisites);
visited = new boolean[numCourses];
onPaths = new boolean[numCourses];
for (int i = 0; i < numCourses; i++) {
traverse(graph, i);
}
return !hasCycle;
}
void traverse(List<Integer>[] graph, int i) {
if (onPaths[i]) {
hasCycle = true;
}
if (visited[i] || hasCycle) {
return;
}
onPaths[i] = true;
visited[i] = true;
for (Integer j : graph[i]) {
traverse(graph, j);
}
onPaths[i] = false;
}
// 构建邻接表
List<Integer>[] buildGraph(int numCourses, int[][] prerequisites) {
List<Integer>[] graph = new ArrayList[numCourses];
for (int i = 0; i < numCourses; i++) {
graph[i] = new ArrayList<>();
}
for (int[] ints : prerequisites) {
graph[ints[1]].add(ints[0]);
}
return graph;
}
}
二、210. 课程表 II
题目链接:https://labuladong.github.io/algo/di-yi-zhan-da78c/shou-ba-sh-03a72/huan-jian–e36de/
思路:上一题是让求有环还是无环,本题是如果没有环返回拓扑排序,那么其实拓扑排序就是后序遍历翻转之后的结果,当我们在构建图的时候,也可以理解为构建树的时候,将箭头指向反过来则无需翻转后序遍历结果。
class Solution {
boolean[] visited;
boolean[] onPaths;
boolean hasCycle;
List<Integer> list;
public int[] findOrder(int numCourses, int[][] prerequisites) {
visited = new boolean[numCourses];
onPaths = new boolean[numCourses];
list = new ArrayList<>();
List<Integer>[] graph = buildGraph(numCourses, prerequisites);
for (int i = 0; i < numCourses; i++) {
travers(graph, i);
}
if (hasCycle) {
return new int[]{};
}
int[] res = new int[numCourses];
for (int i = 0; i < list.size(); i++) {
res[i] = list.get(i);
}
return res;
}
void travers(List<Integer>[] graph, int i) {
if (onPaths[i]) {
hasCycle = true;
}
if (visited[i] || hasCycle) {
return;
}
onPaths[i] = true;
visited[i] = true;
for (Integer j : graph[i]) {
travers(graph, j);
}
list.add(i);
onPaths[i] = false;
}
List<Integer>[] buildGraph(int numCourses, int[][] prerequisites) {
List<Integer>[] graph = new ArrayList[numCourses];
for (int i = 0; i < numCourses; i++) {
graph[i] = new ArrayList<>();
}
for (int[] ints : prerequisites) {
graph[ints[0]].add(ints[1]);
}
return graph;
}
}
本文介绍了力扣平台上的两道关于课程表的算法题目,分别是判断有向图是否存在环(207题)和无环时进行拓扑排序(210题),涉及深度优先遍历、回溯和邻接表的构建。

975

被折叠的 条评论
为什么被折叠?



