一、题目
注意;输入条件是邻接表,而不是邻接矩阵。假设没有重复边
题目分析:
题目是说,课程之间有依赖关系,必须完成一门之前,先完成它的依赖课程。
所以,如果有环的话,就不可能完成所有的课程。因此题目就是判断,图中是否有环。
(1)可以使用深度优先遍历(DFS)
思路是,正在进行该节点的递归深度搜索,如果回到了该节点,就说明有环
(2)可以使用宽度优先遍历(BFS)
记录所有节点的入度
根据入度的计算,搜索完一个节点,把它从途中拿掉,因此后续节点的入度都减一,即将入度为0的节点记录到list中,如果所有节点入度都为0,则无环
二、
(1)DFS
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
//建立邻接表,因为题目中说不让用邻接矩阵
ArrayList[] list=new ArrayList[numCourses];//所有节点
for(int i=0;i<numCourses;i++){
list[i]=new ArrayList<Integer>();//每个节点的后续节点
}
for(int i=0;i<prerequisites.length;i++){
//因为数组后面一项依赖前面一项
list[prerequisites[i][1]].add(prerequisites[i][0]);
}
boolean[] visit=new boolean[numCourses];
for(int i=0;i<numCourses;i++){
if(!dfs(list,visit,i)){//遍历i节点的后续节点 dfs为false表示忧患,进入if循环,返回false
return false;
}
}
return true;
}
//深度遍历,如果节点访问过,返回false 表示有环,不能访问
//如果节点未访问过,将visit设置为true
public boolean dfs(ArrayList[] list, boolean[] visit, int num){
if(visit[num]){
return false;
}
else{
visit[num]=true;
}
for(int i=0;i<list[num].size();i++){//后续节点的dfs
if(!dfs(list,visit,(int)list[num].get(i))){//后续节点i已经访问过
return false;
}
list[num].remove(i);
}
visit[num]=false;
return true;
}
}
(2)BFS
public class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] adj = new List[numCourses];
for(int i = 0; i < numCourses; i++)
adj[i] = new ArrayList<Integer>();
int[] indegree = new int[numCourses];
Queue<Integer> readyCourses = new LinkedList();
int finishCount = 0;
for (int i = 0; i < prerequisites.length; i++)
{
int curCourse = prerequisites[i][0];
int preCourse = prerequisites[i][1];
adj[preCourse].add(curCourse);
indegree[curCourse]++;
}
for (int i = 0; i < numCourses; i++)
{
if (indegree[i] == 0)
readyCourses.offer(i);
}
while (!readyCourses.isEmpty())
{
int course = readyCourses.poll(); // finish
finishCount++;
for (int nextCourse : adj[course])
{
indegree[nextCourse]--;
if (indegree[nextCourse] == 0)
readyCourses.offer(nextCourse); // ready
}
}
return finishCount == numCourses;
}
}