拓扑排序-lc207

280 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

主要用来循环依赖检测。如,[['A', 'B'], ['B', 'C'], ['C', 'D'], ['B', 'D']] => false,[['A', 'B'], ['B', 'C'], ['C', 'A']] => true

注意:建议先学会BFS再解题

接下来请刷题 lc207 leetcode.cn/problems/co…

题目描述

image.png 他会给你学习条件数组,没提及的就是可以自由学,画个图举个例子

n = 6,先决条件表:[[3, 0], [3, 1], [4, 1], [4, 2], [5, 3], [5, 4]]

image.png 一眼看就知道是可以学完的,如果学0需要先学5,那就有循环了,就学不了0,学不完了

解题思路

把能学的先学了,比如 0 1 2 ,再把他们指向的箭头去掉

这样 3 4 前面也没箭头了,也能学了,同上操作,最后发现都学完了那就说明没循环。

这样做,需要一个入度表, [ 0, 0, 0, 2, 2, 2 ] 表示课程0需要前置技能0个,用来知道哪些可以学

一个邻接表,记录课程学完可以学的高阶课程,用来学完剪去箭头

{ '0': [ 3 ], '1': [ 3, 4 ], '2': [ 4 ], '3': [ 5 ], '4': [ 5 ] }

然后就可以 学完能学的,减掉箭头,得到新的能学的,一直循环直到没得学了,如果学到的数量和要求的一致,说明没有循环,能完成课程

比如 dnf 红狗 学了开双刀 才能学 大蹦 ,觉醒技能需要先学 大蹦,那么双刀就是0,大蹦1,觉醒2。把双刀学了,大蹦变成0,觉醒变成1。

代码

var canFinish = function(numCourses, prerequisites) {
    // 拓扑排序
    // 举个例子 6   [[3, 0], [3, 1], [4, 1], [4, 2], [5, 3], [5, 4]]
    // inQuery 记录那些课程的前提课程数量   [ 0, 0, 0, 2, 2, 2 ]  课程0需要前置技能0个
    // 比如 dnf 红狗 学了开双刀 才能学 大蹦 ,觉醒技能需要先学 大蹦,那么双刀就是0,大蹦1,觉醒2
    // map 邻接表,记录课程学完可以学的高阶课程   
    // { '0': [ 3 ], '1': [ 3, 4 ], '2': [ 4 ], '3': [ 5 ], '4': [ 5 ] } 课程0学完可以学3
    let inQuery = new Array(numCourses).fill(0),map = {}
    // 遍历条件数组,得到该要的数据
    prerequisites.forEach(i=>{
        // 可以改一下写法 let [a,b] = i
        inQuery[i[0]]++
        if(map[i[1]]){
            map[i[1]].push(i[0])
        }else{
            map[i[1]]=[i[0]]
        }
    })
    // 找出低阶技能,不需要前提  [ 0, 1, 2 ]
    let query = []
    for(let i=0;i<inQuery.length;i++){
        if(inQuery[i]==0)query.push(i)
    }
    console.log(inQuery,map,query)
    let count = 0
    // 类似BFS,取出不需要前置学习的课程,让他们指向的高阶技能的前置技能数-1,如果变为0那就说明能学了,加进来
    // 就是比如你学了双刀,觉醒需要的前置技能数-1,再学个大蹦就能学了
    // 再遍历,直到能学的都学了,如果学到的和要学的数量是一样的,那就能完成
    while(query.length){
        // 拿到能学的,得到 指向的高阶技能数组
        let a = map[query.shift()]
        count++
        if(a?.length){
            // 遍历指向的高阶技能数组 , -1
            a.forEach(i=>{
                inQuery[i]--
                if(inQuery[i]==0){
                    query.push(i)
                }
            })
        }
    }
    console.log(count)
    return count==numCourses 
};

这个也类似 210. 课程表 II

参考:

拓扑介绍:mp.weixin.qq.com/s/pCRscwKqQ…

别人的题解:leetcode.cn/problems/co…