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?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
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.
这个问题等价于在一个有向图中寻找有没有圈。
我们找到没有入度的节点,删掉它,在其邻接点的入度中将其去掉,再找下一个没有入度的点。
样下来如果没有圈所有的点都会被去掉。如果有圈就剩下了这个圈,他们的入度永远不可能互相去掉。
var canFinish = function(numCourses, prerequisites) {
var num = prerequisites.length;
if (num===0) return true;
var map = {};
var count = 0;
//遍历数组,记录下每个节点的入度和出度
for (let i = 0;i < num;i++) {
if (map[prerequisites[i][0]] === undefined) {
map[prerequisites[i][0]] = [new Set(),new Set()];
count++;
}
if (map[prerequisites[i][1]] === undefined) {
map[prerequisites[i][1]] = [new Set(),new Set()];
count++;
}
//入度
map[prerequisites[i][0]][0].add(prerequisites[i][1]);
//出度
map[prerequisites[i][1]][1].add(prerequisites[i][0]);
}
var lastRemove = [];
var removeing = [];
//找到所有没有入度的点
for (let node in map) {
if (map[node][0].size===0)
lastRemove.push(parseInt(node));
}
while (count !== 0&&lastRemove.length !== 0) {
var numL = lastRemove.length;
count -= numL;
for (let i = 0; i < numL;i++) {
//要删除的节点没有入度,遍历出度数组,找到邻接点们
//从他们的入度中删掉这个点,新的无入度的点将从这里产生
for (var j of map[lastRemove[i]][1]) {
map[j][0].delete(lastRemove[i]);
if (map[j][0].size === 0) removeing.push(j);
}
}
lastRemove = removeing;
removeing = [];
}
//如果没有删除所有的点,就说明有圈
if (count !== 0)
return false;
return true;
};