「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」
题目
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。 请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
示例1
输入:numCourses = 2, prerequisites = [[1,0]]
输出:true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例2
输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
题解
BFS
假设 prerequisites = [[5,8],[3,5],[1,9],[0,2],[4,5],[7,8],[4,9]]
解释:
- 学习 5 之前,需要完成课程 8
- 学习 3 之前,需要完成课程 5
- 学习 1 之前,需要完成课程 9
- 学习 0 之前,需要完成课程 2
- 学习 4 之前,需要完成课程 5
- 学习 7 之前,需要完成课程 8
- 学习 4 之前,需要完成课程 9
课程之间的关系大概如下图所示:
graph LR
8 --> 5 & 7 --> 3 & 4
9 --> 4 & 1
2 --> 0
解决这类有向图问题可以考虑一下从出度入度方面考虑;
| 课程 | 0 | 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| 入度 | 1 | 1 | 0 | 2 | 3 | 1 | 1 | 0 | 0 |
- 观察上表发现,凡是入度为0的,可以直接学习,比如课程2,8,9,其他课程暂时不能学;根据表格入度为0的课程开始学习;
- 将可以入度为0的课程放入队列stack = [2,8,9]
- 学习课程2;学完课程2,通过prerequisites发现,课程0入度需要减1;更新课程队列stack = [8,9,0]
- 此时可以学习课程8,通过prerequisites发现可以将课程5,7的课程入度-1;更新课程队列stack = [9,0,5,7]
- 此时可以学习课程9,通过prerequisites发现可以将课程1,4的课程入度-1;只有课程1的入度这时为0,课程队列stack = [0,5,7,1]
- ...
- 最后所有的课程又可以完成返回true
根据上述思路编辑代码如下:
代码
var canFinish = function (numCourses, prerequisites) {
const len = prerequisites.length;
// 出度,入度 的数组,数组表示当前课程的入度;入度为0,才可以学习;
const outAndIn = Array(numCourses).fill(0);
// 记录课程学完后,将课程相关的入度减小
const keyValue = {};
for (let i = 0; i < len; i++) {
const [a, b] = prerequisites[i];
outAndIn[a]++;
if (keyValue[b]) {
keyValue[b].push(a);
} else {
keyValue[b] = [a];
}
}
// 先找到课程入度为0的课
const stack = [];
for (let i = 0; i < outAndIn.length; i++) {
if (outAndIn[i] === 0) stack.push(i);
}
let count = 0;
while (stack.length) {
count++;
const t = stack.pop();
const next = keyValue[t];
if (next && next.length > 0) {
for (let i = 0; i < next.length; i++) {
outAndIn[next[i]] -= 1;
if (outAndIn[next[i]] === 0) {
stack.push(next[i]);
}
}
}
}
return count === numCourses;
};
var numCourses = 3,
prerequisites = [
[1, 0],
[1, 2],
];
const aa = canFinish(numCourses, prerequisites);
console.log(aa);