你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
来源:力扣(LeetCode)第207题
题目分析
要学习一门课程则必须学习完其所有的先决条件课程,即可以用有向图来描述这种依赖关系,节点间的连接关系不对等。
当前可以上的课即为不依赖于任何一门剩下未学习的课的课,即图中入度为0的节点。可以采用BFS进行搜索访问所有节点。
题目中先决条件使用边缘列表来表示图,转换成图的邻接列表后可以方便的获取某个节点可以访问的节点列表、同时记录节点的入度。
实现步骤
-
图的边缘列表转成邻接列表,并记录节点入度
-
入度为0的节点入队
-
取出队首u,并将u加入结果数据
-
将u的所有邻接点的入度减1,更改后入度为0的节点入队
-
搜索结束后若结果数组的大小等于节点总数则满足要求
代码示例
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> edges(numCourses);//邻接列表
vector<int> inedg (numCourses,0);//入度
for(int i = 0;i < prerequisites.size();i++)
{
int u = prerequisites[i][0];//[u,v],v->u
int v = prerequisites[i][1];
inedg[u]++;//入度加1
edges[v].push_back(u);//添加邻接点
}
int res = 0;
queue<int> myque;
for(int i = 0;i < inedg.size();i++ )
{
if(inedg[i] == 0 )
{
myque.push(i);//入度为0的入队
res++;
}
}
while(!myque.empty())//非空
{
int cur = myque.front();myque.pop();
for(int j = 0;j < edges[cur].size();j++ )//遍历其邻接点
{
int u = edges[cur][j];
inedg[u]--;//入度减一
if( inedg[u] == 0)
{
myque.push(u);
res++;
}
}
}
return res == numCourses;
}
};