题目:
There are a total of n courses you have to take, labeled from 0 to n - 1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
解答:
这是一个有向图问题,所以先建图,然后再扫。
BFS:
每一层都是找出当前不需要prerequisite的课程,即等级为0的课程,当扫到这门课里,把其他需要这门课作为prerequisite的课降一个等级,直到其等级为0时,把它存到queue中作为其他课程可用的prerequisite课。同时记录一共存了多少课程在queue里,这些课都是可以上的课。
public boolean canFinish(int numCourses, int[][] prerequisites) {
if (numCourses <= 1) return true;
if (prerequisites.length == 0 || prerequisites[0].length == 0) return true;
ArrayList[] graph = new ArrayList[numCourses];
int[] degree = new int[numCourses];
for (int i = 0; i < numCourses; i++) {
graph[i] = new ArrayList();
}
for (int[] course : prerequisites) {
degree[course[1]]++;
graph[course[0]].add(course[1]);
}
//BFS
Queue<Integer> q = new LinkedList<>();
int courseRemaining = numCourses;
for (int i = 0; i < numCourses; i++) {
if (degree[i] == 0) {
q.offer(i);
courseRemaining--;
}
}
//Search one and get rid of this one for the all
while(!q.isEmpty()) {
int key = q.poll();
for (int i = 0; i < graph[key].size(); i++) {
int course = (int)graph[key].get(i);
degree[course]--;
if (degree[course] == 0) {
q.offer(course);
courseRemaining--;
}
}
}
return courseRemaining == 0;
}
DFS:
这里把每个点分三种状态:0-没访问,1-正在访问,2-访问结束。每一个点都扫透了,确定这个点跟其他点不会构成deadlock,那么把这个点跟其所有的子结都标成2-访问结束。如果当两个点在同时访问的时候,那么构成死循环,返回false。扫完所有的点都没问题,才返回true。
public boolean DFS(ArrayList[] graph, int course, int[] visited) {
//set 0 as not visited, 1 as visiting, 2 as visited
visited[course] = 1;
for (int i = 0; i < graph[course].size(); i++) {
int curtCourse = (int)graph[course].get(i);
if (visited[curtCourse] == 1) { //if curtCourse is visiting as well, it's a circle
return false;
} else if (visited[curtCourse] == 0) { //if curtCourse hasn't visited yet, go and visit
visited[curtCourse] = 1;
//这里总是忘记,当dfs中case return false时,才return false, 否则继续循环
if(!DFS(graph, curtCourse, visited)) {
return false;
}
}
}
visited[course] = 2;
return true;
}
public boolean canFinish(int numCourses, int[][] prerequisites) {
if (numCourses <= 1) return true;
if (prerequisites.length == 0 || prerequisites[0].length == 0) return true;
ArrayList[] graph = new ArrayList[numCourses];
for (int i = 0; i < numCourses; i++) {
graph[i] = new ArrayList();
}
for (int[] course : prerequisites) {
graph[course[0]].add(course[1]);
}
//DFS
int[] visited = new int[numCourses];
for (int i = 0; i < numCourses; i++) {
if (visited[i] == 2) continue;
if (!DFS(graph, i, visited)) {
return false;
}
}
return true;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。