Leetcode 207. 课程表 / 判断有(无)向图是否存在环路 / python实现

题目

在这里插入图片描述

解题思路

题目相当于在有向图中判断是否存在环路

  1. 拓扑排序
    首先记录所有点的出入度情况,将所有入度为0的点加入队列中,当队列不为空的时候,每次取出队首的点,遍历其邻接点,使得每一个邻接点的入度-1。如果所有曾在队列中的点等于课程数量,说明不存在环路。
  2. DFS,通过记录状态来判断是否存在环路。

代码实现

"""
拓扑排序

1. 将所有入度为0的节点入队列
2. 每次从队列取出一个节点,并将这个节点的所有临界点的入度-1
3. 判断已经处理过的节点是否和课程数量相同

"""
from collections import defaultdict
class Solution:
    def canFinish(self, numCourses: int, prerequisites) -> bool:
        stack = []
        # 记录每个节点的入度
        sin = defaultdict(int)
        # 记录邻接点
        mat = defaultdict(list)
        # y -> x
        for x, y in prerequisites:
            sin[x] += 1
            mat[y].append(x)
        # 将入度为0的点加入队列
        for i in range(numCourses):
            if not sin[i]:
                stack.append(i)
        res = 0
        while stack:
            node = stack.pop(0)
            res += 1
            # 遍历邻接点,其入度-1
            for i in mat[node]:
                sin[i] -= 1
                if not sin[i]:
                    stack.append(i)
        return res == numCourses
"""
判断是否出现环路
"""
from collections import defaultdict
class Solution:
    def canFinish(self, numCourses: int, prerequisites) -> bool:
        mat = defaultdict(list)
        for x, y in prerequisites:
            if y in mat[x]:
                return False
            mat[y].append(x)
        vis = defaultdict(int)
        # 判断是否存在环
        def DFS(s):
        	# 这个节点正在被访问,说明存在环
            if vis[s] == -1:
                return True
            # 已经被访问过了,无须再次访问
            if vis[s] == 1:
                return False
            # 正在被访问
            vis[s] = -1
            for i in mat[s]:
                if DFS(i):
                    return True
            # 该节点访问结束
            vis[s] = 1
            return False
        for i in range(numCourses):
            if not vis[i]:
                if DFS(i):
                    return False
        return True

扩展
判断无向图中是否存在环路,同样采用记录状态的方式,但是需要记录前一个结点

# 无向图判断是否存在环,要记录前一个节点
        def DFS(x, y, prex, prey):
            # 正在被访问
            vis[(x, y)] = -1
            for i in range(4):
                newx, newy = x + dx[i], y + dy[i]
                if newx == prex and newy == prey:
                    continue
                if -1 < newx < len(grid) and -1 < newy < len(grid[0]) and grid[newx][newy] == grid[x][y]:
                    # 存在环
                    if vis[(newx, newy)] == -1:
                        return True
                    if not vis[(newx, newy)]:
                        if DFS(newx, newy, x, y):
                            return True
            vis[(x, y)] = 1
            return False

Guess you like

Origin blog.csdn.net/qq_42711381/article/details/107826015