2025年- G34-Lc108-207. 课程计划--java版
1.题目描述
中文:
课程安排 (Course Schedule) - 题目翻译
你需要完成 numCourses 门课程,课程编号从 0 到 numCourses - 1。
你会得到一个 前置课程要求数组 prerequisites,其中 prerequisites[i] = [a_i, b_i] 表示:
如果你想选修课程 a_i,你必须先完成课程 b_i。
要求
如果你可以完成所有课程,返回 true;否则,返回 false。
2.思路
例子2:
例子2:
3.代码实现
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> gra=new ArrayList<>();
for(int i=0;i<numCourses;i++)
{
gra.add(new ArrayList<>());//构建prerequisites的二维数组, // gra 现在是 [[ ]],// gra 现在是 [[ ], [ ]]
}
for(int[] pre:prerequisites)
{
gra.get(pre[1]).add(pre[0]);///建立先修关系,返回一个新的先修课程的二维数组[[1],[2],[]]
}
//设计一个数组,表示当前点的元素是已访问过
int[] visited=new int[numCourses];// 所有课程初始状态都是 0(未访问)
//3.遍历所有课程,检查是否有环
for(int i=0;i<numCourses;i++)
{
if(dfs(gra,visited,i))
{
return false;
}
}
return true;
}
//4.写个递归调用,用来遍历课程。
//0: 未访问(Not visited)——该节点尚未被访问,或者它的所有邻居都已经被遍历过。
//1: 访问中(Visiting)——该节点正在被访问,或者它位于当前递归路径上。这意味着我们已经进入这个节点,但它的所有邻居尚未被访问。
//2: 已访问(Visited)——该节点已经被完全遍历过,即它的所有邻居已经访问过,且没有发现环。
private boolean dfs(List<List<Integer>> gra, int[] visited, int course) {
if(visited[course]==1)
return true;
if(visited[course]==2)
return false;// 该课程已检查过,无环
// 进入递归,标记为“访问中”
visited[course]=1;
for(int next:gra.get(course))//遍历 course 之后的课程(它的直接后继课程)
{
if(dfs(gra,visited,next))
{
return true;
}
}
// 递归结束,标记为“已完成”
visited[course] = 2;// 【回溯】标记当前课程检查完毕,后续递归不会再访问它
return false;// 没有发现环,返回 false
}
}