207. Course Schedule
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?
部分转载于http://www.cnblogs.com/grandyang/p/4484571.html
这道课程清单的问题对于我们学生来说应该不陌生,因为我们在
选课的时候经常会遇到想选某一门课程,发现选它之前必须先上了哪些课程,这道题给了很多提示,第一条就告诉我们了这道题的本质就是在有向图中检测环。 LeetCode中关于图的题很少,有向图的仅此一道,还有一道关于无向图的题是 Clone Graph 无向图的复制。个人认为图这种数据结构相比于树啊,链表啊什么的要更为复杂一些,尤其是有向图,很麻烦。第二条提示是在讲如何来表示一个有向图,可以用边来表示,边是由两个端点组成的,用两个点来表示边。第三第四条提示揭示了此题有两种解法,DFS和BFS都可以解此题。我们先来看BFS的解法,我们定义二维数组graph来表示这个有向图,一位数组in来表示每个顶点的入度。我们开始先根据输入来建立这个有向图,并将入度数组也初始化好。然后我们定义一个queue变量,将所有入度为0的点放入队列中,然后开始遍历队列,从graph里遍历其连接的点,每到达一个新节点,将其入度减一,如果此时该点入度为0,则放入队列末尾。直到遍历完队列中所有的值,若此时还有节点的入度不为0,则说明环存在,返回false,反之则返回true。代码如下:
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
ArrayList[] graph = new ArrayList[numCourses];
int[] inDegree = new int[numCourses];
for(int i=0;i<numCourses;i++) {
graph[i]=new ArrayList();
}
for(int i=0;i<prerequisites.length;i++) {
int pre=prerequisites[i][1];
int rear=prerequisites[i][0];
inDegree[rear]++;
graph[pre].add(rear);
}
Queue<Integer> queue=new LinkedList<Integer>();
int count=0;
for(int i=0;i<inDegree.length;i++) {
if(inDegree[i]==0) {
queue.offer(i);
count++;
}
}
while(!queue.isEmpty()) {
ArrayList<Integer> rem=graph[queue.poll()];
for(int i=0;i<rem.size();i++) {
int next=rem.get(i);
inDegree[next]--;
if(inDegree[next]==0) {
queue.offer(next);
count++;
}
}
}
return count==numCourses;
}
}
下面我们来看DFS的解法,也需要建立有向图,还是用二维数组来建立,和BFS不同的是,我们像现在需要一个一维数组visit来记录访问状态,这里有三种状态,0表示还未访问过,1表示已经访问了,-1表示有冲突。大体思路是,先建立好有向图,然后从第一个门课开始,找其可构成哪门课,暂时将当前课程标记为已访问,然后对新得到的课程调用DFS递归,直到出现新的课程已经访问过了,则返回false,没有冲突的话返回true,然后把标记为已访问的课程改为未访问。代码如下:
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
ArrayList[] graph = new ArrayList[numCourses];
int[] visit = new int[numCourses];
for(int i=0;i<numCourses;i++) {
graph[i]=new ArrayList();
}
for(int i=0;i<prerequisites.length;i++) {
int pre=prerequisites[i][1];
int rear=prerequisites[i][0];
graph[pre].add(rear);
}
for(int i=0;i<graph.length;i++) {
if(!dfsHelper(graph,i,visit))
return false;
}
return true;
}
public boolean dfsHelper(ArrayList[] graph,int i,int[] visit) {
if(visit[i]==1)return true;
if(visit[i]==-1)return false;
visit[i]=-1;
for(int j=0;j<graph[i].size();j++) {
if(!dfsHelper(graph,(int)graph[i].get(j),visit))
return false;
}
visit[i]=1;
return true;
}
}