1. 题目描述
2. Solution 1
1、思路分析
This problem is equivalent to detecting a cycle in the directed graph represented by prerequisites. Both BFS and DFS can be used to solve it using the idea of topological sort. Since pair<int, int> is inconvenient for implementing graph algorithms, we first transform it to the adjacency-list representation. If course u is a prerequisite of course v, then the adjacency list of u will contain v.
BFS
BFS uses the indegrees of each node. We will first try to find a node with 0 indegree. If we fail to do so, there must be a cycle in the graph and we return false. Otherwise we set its indegree to be -1 to prevent from visiting it again and reduce the indegrees of its neighbors by 1. This process will be repeated for n (number of nodes) times.
2、代码实现
package Q0299.Q0207CourseSchedule;
import java.util.ArrayList;
import java.util.List;
/*
This problem is equivalent to detecting a cycle in the directed graph represented by prerequisites. Both BFS and
DFS can be used to solve it using the idea of topological sort. Since pair<int, int> is inconvenient for
implementing graph algorithms, we first transform it to the adjacency-list representation. If course u is a
prerequisite of course v, then the adjacency list of u will contain v.
BFS
BFS uses the indegrees of each node. We will first try to find a node with 0 indegree. If we fail to do so, there
must be a cycle in the graph and we return false. Otherwise we set its indegree to be -1 to prevent from visiting
it again and reduce the indegrees of its neighbors by 1. This process will be repeated for n (number of nodes) times.
*/
public class Solution1 {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> g = buildGraph(numCourses, prerequisites);
List<Integer> degrees = computerIndegrees(g);
for (int i = 0; i < numCourses; i++) {
int j = 0;
for (; j < numCourses; j++)
if (degrees.get(j) == 0) break; // 找到了入度为0的顶点,作为遍历的起点
if (j == numCourses) return false; // 没有找到入度为0的顶点
degrees.set(j, degrees.get(j) - 1);
for (int v : g.get(j)) degrees.set(v, degrees.get(v) - 1);
}
return true;
}
/*
[1, 0] To take course 1 you should have finished course 0, 0 -> 1.
对于 p=prerequisites[i] 中的数对,边的方向是 p[1] -> p[0]
使用邻接表的方式存储图
*/
private List<List<Integer>> buildGraph(int numCourses, int[][] prerequisites) {
List<List<Integer>> g = new ArrayList<>();
for (int i = 0; i < numCourses; i++) g.add(new ArrayList<>());
for (int[] p : prerequisites)
g.get(p[1]).add(p[0]); // p[1] -> p[0]
return g;
}
// 计算上面构建的图结构中,每个点的入度
List<Integer> computerIndegrees(List<List<Integer>> g) {
List<Integer> degrees = new ArrayList<>();
for (int i = 0; i < g.size(); i++) degrees.add(0);
for (List<Integer> adj : g) {
for (int v : adj) {
degrees.set(v, degrees.get(v) + 1);
}
}
return degrees;
}
}
3、复杂度分析
时间复杂度: O(m+n)
空间复杂度: O(m+n)
3. Solution 2
1、思路分析
DFS
For DFS, in each visit, we start from a node and keep visiting its neighbors, if at a time we return to a visited node, there is a cycle. Otherwise, start again from another unvisited node and repeat this process. We use todo and done for nodes to visit and visited nodes.
2、代码实现
package Q0299.Q0207CourseSchedule;
import java.util.ArrayList;
import java.util.List;
/*
DFS
For DFS, in each visit, we start from a node and keep visiting its neighbors, if at a time we return to a visited
node, there is a cycle. Otherwise, start again from another unvisited node and repeat this process. We use todo
and done for nodes to visit and visited nodes.
*/
public class Solution2 {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> g = buildGraph(numCourses, prerequisites);
boolean[] todo = new boolean[numCourses], done = new boolean[numCourses];
for (int i = 0; i < numCourses; i++) {
if (!done[i] && !acylic(g, todo, done, i)) return false;
}
return true;
}
private boolean acylic(List<List<Integer>> g, boolean[] todo, boolean[] done, int node) {
if (todo[node]) return false;
if (done[node]) return true;
todo[node] = done[node] = true;
for (int v : g.get(node)) {
if (!acylic(g, todo, done, v)) return false;
}
todo[node] = false;
return true;
}
private List<List<Integer>> buildGraph(int numCourses, int[][] prerequisites) {
List<List<Integer>> g = new ArrayList<>();
for (int i = 0; i < numCourses; i++) g.add(new ArrayList<>());
for (int[] p : prerequisites)
g.get(p[1]).add(p[0]);
return g;
}
}
3、复杂度分析
时间复杂度: O(m+n)
空间复杂度: O(m+n)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。