Leetcode 210.课程表II(拓扑排序,804)

0 阅读2分钟

题目

image.png

26年8月4日(少部分自解)

func findOrder(numCourses int, prerequisites [][]int) []int {
    nodein:=make([]int,numCourses) //入度表
    graph:=make([][]int,numCourses) //邻接表
    res:=make([]int,0,numCourses)//注意
    for i:=0;i<len(prerequisites);i++{
        next,pre:=prerequisites[i][0],prerequisites[i][1]
        nodein[next]++
        graph[pre]=append(graph[pre],next)
    }
    visited:=make([]bool,numCourses)
    queue:=[]int{}
    for i:=range nodein{
        if nodein[i]==0{
        queue=append(queue,i)
         visited[i]=true
        res=append(res,i)
        //多入度0初始化没考虑       
        }
    }
    for len(queue)>0{
        cur:=queue[0]
        queue=queue[1:]
        for _,v:=range graph[cur]{
            if visited[v]==true{
                continue
            }
            //判断顺序错
            nodein[v]--
            if nodein[v]==0{
                queue=append(queue,v)
                res=append(res,v)
                visited[v]=true
            }
        }
    }
    if len(res)==numCourses{
        return res
    }else{
        return []int{}
    }
}

思路

拓扑排序(BFS),使用于比如有先置条件的有向图。比如选了课程0,才能选课程1,选了课程2,才能选课程1。等等

image.png

这样形成依赖关系后,会形成如图的关系。这样我们能发现规律,最开始要选入度为0的节点,也就是没有先置条件的。比如这里选0,而选了0后,对于1和2他们的先置条件满足了可以选了,对应图中我们此时把0去掉,让节点1和2的入度-1变为0。这样就比较好想代码逻辑,是类似队列BFS的

对于删除节点,我们就用visited数组标记模拟

这样我们在标记visit,同时能避免后续的节点选择到之前已经加入队列的入度为0的节点。

然后我们删除后,还有把这个入度节点指向的next节点的入度-1,所以我们一开始不仅要记录入度,如下

nodein:=make([]int,numCourses)//入度表

还有记录指向关系,graph邻接表,能寻找到next节点。

graph:=make([][]int,numCourses) //邻接表

不过这道题还有坑,就是可能会出现有环的情况,都出现环了说明之前选过肯定不能选,但是并不是有环就一定不能选完所有节点。

if visited[v]==true{ continue }

这里visited数组再次发挥作用,先判断之前有没有遍历过,如果遍历过说明这里出现后环了,那么就跳过。