拓扑排序之 leetcode 207.课程表

 原题:207. 课程表 - 力扣(LeetCode)

这是一道经典的拓扑排序题目,为理解和解决这类题目,我们首先了解下拓扑排序。

在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列,它有以下性质

(1)唯一性

当有向无环图呈线性结构(即从第一个节点到最后一个节点有一条路径连接所有节点)时,拓扑排序唯一。当图中存在多个无依赖关系的节点时,拓扑排序不唯一。

(2)时间复杂度

Kahn算法和DFS算法的时间复杂度均为O(V+E),其中V是节点数,E是边数。两种算法都能高效处理大规模图结构。

(3)环检测(这个是解题的关键)

如果算法结束后拓扑排序的节点数少于图中总节点数,说明图中存在环。这使得拓扑排序算法同时成为检测有向图是否有环的有效方法。

其他背景:

什么是度?出度?入度?

​​​​​https://zh.wikipedia.org/wiki/%E5%BA%A6_(%E5%9B%BE%E8%AE%BA)

解法:

这里主要分为两种,第一种是BFS广度优先搜索(基于入度的Kahn算法),第二种是DFS深度优先搜索。

(1)BFS

func canFinish(numCourses int, pre [][]int) bool {
    edges := make(map[int][]int,numCourses)
    indges := make([]int,numCourses)
    for i := range pre {
        p:=pre[i]
        edges[p[1]] = append(edges[p[1]],p[0])
        indges[p[0]]++
    }

    q:=[]int{}
    for i := range indges {
        if indges[i]== 0 {
            q = append(q,i)
        }   
    }

    result := []int{}
    for len(q)>0 {
        u := q[0]
        q=q[1:]
        result = append(result,u)
        for _,v:=range edges[u] {
            indges[v]--
            if indges[v] == 0 {
                q = append(q,v)
            }
        } 
    }
    return len(result) == numCourses

}

(2) DFS

func canFinish(numCourses int, pre [][]int) bool {
    edges := make([][]int,numCourses)
    visited := make([]int,numCourses)
    valid := true 
    result := make([]int,0,numCourses)
    var dfs  func(k int )
    dfs = func(k int ) {
        visited[k] = 1  // 
        for _,u := range edges[k] {
            if visited[u] == 0 {
                dfs(u)
                if !valid {
                    return 
                }
            }else if visited[u] == 1 {
                valid = false
                return 
            }
        }
        visited[k] = 2
        result = append(result,k)
    }

    for i := range pre {
        p := pre[i]
        edges[p[1]] = append(edges[p[1]],p[0])
    }
    for i :=0;i<numCourses && valid;i++{
        if visited[i] == 0 {
            dfs(i)
        }
    }
    return valid

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值