207.课程表|拓扑排序|判断有向图是否有环|深度遍历|广度遍历

在这里插入图片描述

读题:已知边,判断该有向图是否有环。

参考链接:「图解」拓扑排序 | 课程表问题

把一个 有向无环图 转成 线性的排序 就叫 拓扑排序

  • BDF 广度遍历
  • 1、根据pre得indegree入度数组、adject邻接表
  • 2、queue保存入度为0的结点(即没有前提课程的课程)
  • 3、根据queue减少相邻结点的入度(根据adject邻接表),减到0后入队列;
  • 4、队列空了后,还有入度不为0的课程(即numCourse!=0)就返回False。
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 看有没有环, True:没有环
        # 仔细读题:prerequisites相当于给出了边
        # 广度遍历
        inDegree = [0] * numCourses # 记录每个结点的入度
        # print(inDegree)
        adject = [[] for _ in range(numCourses)] # 通过边,填写二维数组邻接表
        # adject = [[] * numCourses] # 这样不行! adject = [[]]
        # print(adject) 

        for edge in prerequisites:
            inDegree[edge[0]] += 1 # 入度加一
            adject[edge[1]].append(edge[0]) # 选学了b才能学a,故边由b指向a
        
        queue = [] # 队列中放入度为0的结点
        for i in range(numCourses):
            if inDegree[i] == 0: # 如果结点的入度为0,则入队列
                queue.insert(0, i)
        
        while queue:
            prerequisite = queue.pop() # 取出入度为0的课程,调整学习该课程后的其他节点的入度(根据邻接表找)
            numCourses -= 1 # 剩余学习课程-1
            # print(adject)
            # print(prerequisite)
            for course in adject[prerequisite]:
                # print(course)
                inDegree[course] -= 1 # 入度-1,就是前提课程-1
                if not inDegree[course]:
                    queue.insert(0, course) # 入度为0的结点入队列
        
        return not numCourses # 如果剩余学习课程为0,就返回true


  • 深度遍历
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 看有没有环, True:没有环
        # 仔细读题:prerequisites相当于给出了边
        # 深度遍历
        
        self.adject = [[] for _ in range(numCourses)] # 邻接表
        self.flag = [0 for _ in range(numCourses)] 
        # 标记,-1表示该结点已经被检查过不是构成环的结点;1表示本轮正在检查的结点,如果这轮又遇到了1就说明有环;0表示没有访问过
        
        for edge in prerequisites:
            self.adject[edge[1]].append(edge[0]) # 邻接表,学完前提课程edge[1],才能学edge[0]


        def dfs(i):
            if self.flag[i] == -1:
                return True
            if self.flag[i] == 1:
                return False
            self.flag[i] = 1 # 本轮遍历的标记
            for j in self.adject[i]:
                if dfs(j) == False:
                    return False
            self.flag[i] = -1 # 经过检验了
            return True

        for i in range(numCourses):
            if dfs(i) == False: # 遍历结点
                return False
        
        return True

在这里插入图片描述
参考链接:课程表(拓扑排序:入度表BFS法 / DFS法,清晰图解)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值