题目的链接在这里:https://leetcode-cn.com/problems/course-schedule/
题目大意
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
一、示意图
二、解题思路
深度遍历和广度遍历
深度遍历
代码如下:
class Solution {
List<List<Integer>> edges;
//然后是判断是否有效
boolean valid;
//好像都不需要存数组
/* //一个用来存数据的数组
int[]res;
//一个记录数组位置的
int index;*/
//一个判断对应的点有没有访问过 0表示没有访问过 1表示在访问中 2表示已经访问过了
int visited[];
public boolean canFinish(int numCourses, int[][] prerequisites) {
//这里就变成了 判断可不可以了 其实就是最后判断那个序列的长度等不等于 numCourses
//先用用看DFS
//首先就是需要构造这个有向图
//开始初始化
edges=new ArrayList<List<Integer>>();
valid=true;
/* res=new int[numCourses];
index=numCourses-1;*/
visited=new int[numCourses];
for(int i=0;i<numCourses;i++){
edges.add(new ArrayList<Integer>());
}
//然后开始构造图
for(int []infor:prerequisites){
//数组是 a b的话 表示就是 从b指向a 这样子就构成边了
edges.get(infor[1]).add(infor[0]);
}
//然后就是遍历 找到第一个没有被访问过的 然后就开始访问
for(int i=0;i<numCourses&&valid;i++){
//找到第一个没有被访问过的
if(visited[i]==0){
//那就进行递归
dfs(i);
}
}
//最后这里进行判断
return valid;
}
private void dfs(int i) {
//就开始深度遍历 首先进行改变
//变成正在访问中
visited[i]=1;
//然后找从这个点出去的节点
for(int v:edges.get(i)){
//这里可能就会有好几个
//如果没有访问过就进行访问 如果表示在访问中 那就说明有环 直接返回
if(visited[v]==0){
dfs(v);
}
else if(visited[v]==1){
valid=false;
return;
}
}
//然后把这个点改成 已经完成了
visited[i]=2;
}
}
广度遍历
代码如下:
class Solution {
List<List<Integer>> lists;
//存储数组的计数
int count;
//然后记录每个点的入度
int inDu[];
public boolean canFinish(int numCourses, int[][] prerequisites) {
//然后是BFS 这个的话 要么就是通过这个这个最后的计数好了
//开始初始化
count=0;
inDu=new int[numCourses];
lists=new ArrayList<List<Integer>>();
for(int i=0;i<numCourses;i++){
lists.add(new ArrayList<Integer>());
}
//然后开始初始化 并且记录对应的入度
for(int[] infor:prerequisites){
//对应这个数组来说 他是 infor[1]->infor[0]
inDu[infor[0]]++;
//然后是边进行放入
lists.get(infor[1]).add(infor[0]);
}
//然后创建一个队列 并将入度为0的全都放到队列中 并进行记录
Queue<Integer> queue=new LinkedList<Integer>();
for(int i=0;i<numCourses;i++){
if(inDu[i]==0){
//说明入度是0
queue.add(i);
count++;
}
}
//然后开始一个个判断
while (!queue.isEmpty()){
int node=queue.poll();
//然后更新node这个点出去的点 消除对应的入度
for(int v:lists.get(node)){
//他们对应的入度减一
inDu[v]--;
if(inDu[v]==0){
//那就进栈 并且进行更新
count++;
queue.add(v);
}
}
}
//最后就是判断count和numCourses的大小
return count==numCourses;
}
}