[路飞]_一起刷leetcode 210. 课程表 II

这是我参与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,这样子才满足一个队列先进先出的情况,如果前面排队的被后面来的插队应该会很不爽吧哈哈。

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。

猜你喜欢

转载自juejin.im/post/7055955810148581406