这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战
题目
210. 课程表 II
现在你总共有 numCourses
门课需要选,记为 0
到 numCourses - 1
。给你一个数组 prerequisites
,其中 prerequisites[i] = [ai, bi]
,表示在选修课程 ai
前 必须 先选修 bi
。
- 例如,想要学习课程
0
,你需要先完成课程1
,我们用一个匹配来表示:[0,1]
。
返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。
示例 1:
输入: numCourses = 2, prerequisites = [[1,0]]
输出: [0,1]
解释: 总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。
复制代码
示例 2:
输入: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
输出: [0,2,1,3]
解释: 总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 。
复制代码
示例 3:
输入: numCourses = 1, prerequisites = []
输出: [0]
复制代码
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= numCourses * (numCourses - 1)
prerequisites[i].length == 2
0 <= ai, bi < numCourses
ai != bi
- 所有
[ai, bi]
互不相同
思路
这道题目跟我们上次做过的一起刷leetcode 207. 课程表 属于兄弟题目,如果理解了上一篇文章,那么这道题目基本也没什么难度,可以把result
完成数量改成数组,然后遍历的时候把result++
改成result.push(xxx)
,最终返回的时候判断result.length
是否等于numCourses
, 如果不等于说明没有全部做完,这时候返回一个空数组即可,如果等于说明做完了,这时候就直接返回result
。
实现
/**
* @param {number} numCourses
* @param {number[][]} prerequisites
* @return {number[]}
*/
var findOrder = function(numCourses, prerequisites) {
let list = new Array(numCourses).fill(0);
let map = new Map();
// 建立拓扑关系
for (let i = 0; i < prerequisites.length; i++) {
const [ a, b ] = prerequisites[i];
list[a]++;
map.set(b, (map.get(b) || []).concat([ a ]));
}
// 记录做完的课程
let doneList = [];
let result = [];
for (let i = 0; i < numCourses; i++) {
if (list[i] === 0) {
doneList.push(i);
result.push(i);
}
}
while (doneList.length) {
// 挨个去广播处通知所有相关的小伙伴
const cur = doneList.shift();
const temp = map.get(cur) || [];
for (let i = 0; i < temp.length; i++) {
list[temp[i]]--;
if (list[temp[i]] === 0) {
doneList.push(temp[i]);
result.push(temp[i]);
}
}
}
return result.length === numCourses ? result : [];
};
复制代码
然后再教大家一个小技巧,如果想提升性能的话把while
循环中的shift
改成pop
可以快一些,因为shift
操作从最前面删除掉某个元素,会导致后面的元素全都需要往前挪一位,而pop
是直接删除最后一个元素,对前面的元素没有任何影响。但是我还是依然选择用shift
,这样子才满足一个队列先进先出的情况,如果前面排队的被后面来的插队应该会很不爽吧哈哈。
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。