【python数据结构】二分图、拓扑排序、并查集

本文深入讲解了图算法中的关键概念,包括二分图判断、拓扑排序及其在课程安排中的应用,以及并查集在判断冗余连接中的使用。通过具体实例和代码,详细解析了这些算法的工作原理和实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.判断是否为二分图【leetcode785】

如果可以用两种颜色对图中的节点进行着色,并且保证相邻的节点颜色不同,那么这个图就是二分图。

class Solution:
    def isBipartite(self, graph: List[List[int]]) -> bool:
        color = {}
        for node in range(len(graph)):
            if node not in color:
                stack = [node]
                color[node] = 0
                while stack:
                    cur = stack.pop()
                    for nxt in graph[cur]:
                        if nxt not in color:
                            stack.append(nxt)
                            color[nxt] = color[cur]^1
                        elif color[cur] == color[nxt]:
                            return False
        return True

2.拓扑排序

常用于在具有先序关系的任务规划中。

课程安排的合法性【leetcode207】

    #BFS:创建入度表 
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        indegrees = [0 for _ in range(numCourses)]
        adjacency = [[] for _ in range(numCourses)]#邻接表
        queue = []

        # get the indegree and adjacency of every course
        for cur, pre in prerequisites:
            indegrees[cur] += 1 #表明修cur之前需要先修pre,所以cur的入度+1
            adjacency[pre].append(cur) 
        
        for i in range(len(indegrees)):
            if indegrees[i] == 0:#入度为0的课程不需要依赖,直接可以修
                queue.append(i)
        while queue:
            pre = queue.pop(0)
            numCourses -= 1
            for cur in adjacency[pre]:
                indegrees[cur] -= 1
                if indegrees[cur] == 0:
                    queue.append(cur)
        return not numCourses
class Solution:  
    # 深度优先遍历:通过DFS判断图中是否有环
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        #1、借助一个标志列表flags,用于判断每个节点i的状态:
        # (1)未被DFS访问,i==0
        #  (2)已经被其他节点启动的DFS访问,i == -1
        # (3)已被当前节点启动的DFS访问,i == 1
        #2、对numCourses的节点依次执行DFS,判断每个节点起步DFS是否存在环,若存在环直接返回False
        # DFS的流程如下:
        # (1)终止条件:当flag[i] == -1, 表明节点已经被其他节点启动的DFS访问,无需重复搜索,直接返回True
        # 当flag[i] == 1, 表明节点i在本轮DFS中第二次被访问到,即有环,直接返回False
        # (2)将当前访问节点i对应flag[i]置为1,即标记其被本轮DFS访问过
        # (3)递归访问当前节点i的所有邻接节点j,发现有环直接返回False
        # (4)当前节点所有邻接节点已被遍历,并没有发现环,则将当前节点flag设置为-1并返回True
        # 3、若整个图DFS结束并未发现环,返回True
        def dfs(i, adjacency, flags):
            if flags[i] == -1: return True 
            if flags[i] == 1: return False 
            flags[i] = 1
            for j in adjacency[i]:
                if not dfs(j, adjacency, flags): return False 
            flags[i] = -1
            return True 
        adjacency = [[] for _ in range(numCourses)]
        flags = [0 for _ in range(numCourses)]
        for cur, pre in prerequisites:
            adjacency[pre].append(cur)
        for i in range(numCourses):
            if not dfs(i, adjacency, flags): return False
        return True

3.课程安排的顺序【leetcode210】

class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]):
        indegrees = [0 for _ in range(numCourses)]
        adjacency = [[] for _ in range(numCourses)]
        for cur, pre in prerequisites:
            indegrees[cur] += 1
            adjacency[pre].append(cur)
        queue = []
        ans = []
        for i in range(len(indegrees)):
            if indegrees[i] == 0:
                queue.append(i)
        while queue:
            pre = queue.pop(0)
            ans.append(pre)
            numCourses -= 1
            for cur in adjacency[pre]:
                indegrees[cur] -= 1
                if indegrees[cur]==0:
                    queue.append(cur)
        if not numCourses:return ans
        else:return []

4.并查集判断冗余连接【leetcode684】

# 这个并查集是比较简单的,没有压缩路径
class disjoint:
    def __init__(self, N):
        self.array = [-1] * N
        
    def find_root(self, i):
        while self.array[i] != -1:
            i = self.array[i]
        return i
    
    def union(self, i, j):
        i = self.find_root(i)
        j = self.find_root(j)
        if (i != j) or (i == -1 and j == -1):
            self.array[i] = j
            return j
        else:
            return -1
    
        
class Solution:
    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        a = set()
        for i in edges:
            a.add(i[0])
            a.add(i[1])
            
        tree = disjoint(2*len(edges) + 1)
        
        answer = None
        
        for i in edges:
            x, y = tree.find_root(i[0]), tree.find_root(i[1])
            if (x != y) or (x == -1 and y == -1):
                tree.union(i[0], i[1])
            else:
                answer = i
        
        return answer

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值