Question
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?
Example 1:
Input: 2, [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: 2, [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should
also have finished course 1. So it is impossible.
Note:
- The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
- You may assume that there are no duplicate edges in the input prerequisites.
Algorithm
这一题是典型的拓扑排序(Topological sort),在解这题之前我是没有看过图相关的算法,仅仅知道一些基本概念。学过图论的可以直接看代码了。
在解这道题之前,我们需要知道几个概念:
- 有向图(Directed Graph)
- 邻接表(Adjacency-list)
- 出度(out degree)
- 入度(in degree)
接着我们需要知道用什么数据结构来表示一张图:
- 可以用一维结构体数组或者二维数组,这里我用二维数组
给出的Hint中写到:
This problem is equivalent to finding if a cycle exists in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
这个问题的实质是判断有向图中是否存在环,如果存在环,则不存在拓扑排序(有向无环图才存在拓扑排序),也就无法上完所有课程。这里我找到一个介绍拓扑排序的博客拓扑排序(Topological Sorting)
For example:(BFS)
简单来说,步骤如下:
- 找一个入度为0的顶点(任意,因此拓扑排序的结果不是唯一的)
- 去掉这个顶点,并且删除所有连接的边
- 重复1.2
以拓扑排序的方法为基础,来判断有向图是否有环:
在步骤1.2.3的过程中,统计入度为0的顶点个数count,判断count是否等于图的顶点个数
For example:
一、在刚才的例子中
(1)找到1的入度为0,count+1=1
(2)找到2的入度为0,count+1=2
…最后count = 5,图中的顶点个数也是5,所以存在拓扑排序
二、题目中Example2,0->1,1->0
没有入度为0的顶点,因此count=0,顶点数为2,所以不存在拓扑排序
现在回到题目中来,那么课程就是顶点,(1,0)表示上完课程0才能上课程1,那在有向图中应该是表示0->1(这个别搞错了)
Code
//step1: establish adjacency-list & count indegree
//step2: find point of indegree is zero
//step3: BFS
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<vector<int> > graph(numCourses);
vector<int> indegree(numCourses, 0);
//establish adjacency-list & count indegree
for(auto p : prerequisites){
graph[p.second].push_back(p.first);
indegree[p.first]++;
}
//find point of indegree is zero
queue<int> Q;
for(int i=0; i<numCourses; i++){
if(indegree[i] == 0){
Q.push(i);
}
}
//BFS
int count = 0;
while(!Q.empty()){
int cur = Q.front();
Q.pop();
count++;
for(auto cur : graph[cur]){
indegree[cur]--;
if(indegree[cur] == 0)
Q.push(cur);
}
}
return count == numCourses;
}
};