2021-07-07:刷题:图785二分图,染色法,886,DFS课程表207,210,并查集判断有无环684

本文深入探讨了图论中的二分图染色问题,通过遍历和深度优先搜索算法实现节点的正确染色。同时,分析了环形图的检测方法,包括课程表的依赖关系处理和冗余连接的查找。通过对错误代码的分析和纠正,展示了如何避免常见误区,提高算法效率。
摘要由CSDN通过智能技术生成

785

二分图:
染色法:

思路,遍历图,如果是表格的话每个点会被遍历两遍。在第一遍里面,如果判断到此处color为0,还未上色的时候先涂色,然后用dfs去遍历它的临近点,如果临近点color也是0的话就继续涂色。遍历每个点第二次的时候再去确认是不是符合条件的。涂色和确认的条件都在dfs里面实现

问题代码:

class Solution:
    def isBipartite(self, graph: List[List[int]]) -> bool:
        N = len(graph)
        colors = [0]*N
        pad = [[0]*N for _ in range(N)]
        for i in range(N):
            for j in graph[i]:
                pad[i][j] == 1
        for n in range(N):
            if colors[n] == 0 and not self.dfs(N,colors,pad,n,1):
                return False
        return True
    
    def dfs(self,N,colors,pad,i,color):
        colors[i] = color
        for j in range(N):
            if pad[i][j] == 1:
                if color == colors[j]:
                    return False
                if colors[j] == 0 and not self.dfs(N,colors,pad,n,-1*color):
                    return False
        return True

        

问题:1. pad[i][j] =1 不是 ==

2. dfs里,二次循环迭代的是j。从第 i点遍历其 j点邻居

正确代码:

class Solution:
    def isBipartite(self, graph: List[List[int]]) -> bool:
        n = len(graph)
        m = len(graph[0])
        colors = [0]*n
        pad = [[0]*n for _ in range(n)]
        for i in range(n):
            for x in graph[i]:
                pad[i][x] = 1
        for k in range(n):
            if colors[k] == 0 and not self.dfs(k,colors,pad,1,n):
                return False
        return True
    def dfs(self,i,colors,pad,color,n):
        colors[i] = color
        for j in range(n):
            if pad[i][j] == 1:
                if color == colors[j]:
                    return False
                if colors[j] == 0 and not self.dfs(j,colors,pad,-1*color,n):
                    return False
        return True

时间复杂度 N^2

空间复杂度 N^2

886,可能的二分法:

class Solution:
    def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
        colors = [0]* n
        pad = [[0]*n for _ in range(n)]
        for i in range(len(dislikes)):
                p1 = dislikes[i][0]
                p2 = dislikes[i][1]
                pad[p1-1][p2-1] = 1
                pad[p2-1][p1-1] = 1
        for k in range(n):
            if colors[k] == 0 and not self.dfs(colors,n,pad,k,1):
                return False
        return True
    def dfs(self,colors,n,pad,i,color):
        colors[i] = color
        for j in range(n):
            if pad[i][j] == 1:
                if colors[j] == color:
                    return False
                if colors[j] == 0 and not self.dfs(colors,n,pad,j,-1*color):
                    return False
        return True

环形图:

 

问题代码:

class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        adjacency = [[]for _ in range(numCourses)]
        flag = [0]*numCourses
        for n in range(numCourses):
            for pre,cur in prerequisites[n]:
                adjacency[pre].append(cur)
        for i in range(numCourses):
            for j in adjacency[i]:
                if not self.dfs(j,adjacency,flag):
                    return False
        return True
    def dfs(self,i,adjacency,flag):
        if flag[i] == -1: 
            return True
        if flag[i] == 1:
            return False
        flag[i] = 1
        for j in adjacency[i]:
            if not self.dfs(j,adjacency,flag):
                return False
        flag[i] = -1
        return True 


        

问题:

1. 先是cur 再是pre

2.这里遍历例如prerequisites

 [[1,0],[0,1]]的时候:

for x in prerequisites: 表示遍历[1,0]      [0,1]

for pre,cur in prerequisites:  表示遍历[1=pre,0=cur] , [0=pre,1=cur]

for n in prerequisites:  for  i in prerequisites[n]: 表示遍历 1,0, 0, 1

正确代码:

class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        adjacency = [[]for _ in range(numCourses)]
        flag = [0]*numCourses
        for cur,pre in prerequisites:
                adjacency[pre].append(cur)
        for i in range(numCourses):
            if not self.dfs(i,adjacency,flag):
                return False
        return True
    def dfs(self,i,adjacency,flag):
        if flag[i] == -1: 
            return True
        if flag[i] == 1:
            return False
        flag[i] = 1
        for j in adjacency[i]:
            if not self.dfs(j,adjacency,flag):
                return False
        flag[i] = -1
        return True 

课程表2:

class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
        self.adjacency = [[]for _ in range(numCourses)]
        flag = [0]*numCourses
        self.res = []
        for cur, pre in prerequisites: 
            self.adjacency[cur].append(pre)
        for i in range(numCourses):
            if not self.dfs(flag,i):
                return []
        return self.res
    def dfs(self,flag,i):
        if flag[i] == 1:
            return False
        if flag[i] == -1:
            #无需遍历
            return True
        flag[i] = 1
        for j in self.adjacency[i]:
            if not self.dfs(flag,j):
                return False
        flag[i] = -1
        self.res.append(i) #第二次返回的时候再加上。说明已经是cur.pre.pre非常深入了
        return True

时间复杂度: 错误N^2   正确M+N  M表示多少个点 ,N表示多少条边

空间复杂度:错误N^2    正确M+N  M表示多少个点,N表示多少条边

684:冗余连接(判断题目是否有环,并返回使环连接的最后两个点)

 

错误代码:

class UF:
    def __init__(self,M):
        self.size = {}
        self.parent = {}
        self.count = 0
        for i in range(M):
            self.size[i] = 1
            self.parent[i] = i
            self.count += 1
    def find(self,x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def union(self,x,y):
        if self.size[x] > self.size[y]:
            self.parent[y] = self.find(x)
        elif self.size[x] < self.size[y]:
            self.parent[x] = self.find(y)
        else:
            self.parent[y] = self.find(x)
            self.size[x] += 1
        self.count -= 1
    def connected(self,x,y):
        if self.find(x) == self.find(y):
            return True
        else:
            return False

class Solution:
    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        uf = UF(1001)
        for x,y in edges:
            if uf.connected(x,y):
                 return [x,y]
            uf.union(x,y)

错误原因,unionfind里面的union写的有问题。这里的size指root下面点的多少

正确代码:

class UF:
    def __init__(self,M):
        self.size = {}
        self.parent = {}
        self.count = 0
        for i in range(M):
            self.size[i] = 1
            self.parent[i] = i
            self.count += 1
    def find(self,x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def union(self,x,y):
        if self.connected(x,y): return
        rootx = self.find(x)
        rooty= self.find(y)
        if self.size[rootx] <self.size[rooty]:
            self.parent[rootx] = rooty
            self.size[rooty] += self.size[rootx]
        else:
            self.parent[rooty] = rootx
            self.size[rootx] += self.size[rooty]   
        self.count -= 1
    def connected(self,x,y):
        return self.find(x) == self.find(y)


class Solution:
    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        uf = UF(1001)
        for x,y in edges:
            if uf.connected(x,y):
                 return [x,y]
            uf.union(x,y)

优化代码:

此处并查集用rank.时间会更高效

class UF:
    def __init__(self,M):
        self.rank = {}
        self.parent = {}
        self.count = 0
        for i in range(M):
            self.rank[i] = 1
            self.parent[i] = i
            self.count += 1
    def find(self,x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def union(self,x,y):
        if self.connected(x,y): return
        rootx = self.find(x)
        rooty= self.find(y)
        if self.rank[rootx] < self.rank[rooty]:
            self.parent[rootx] = rooty
            self.rank[rootx] = self.rank[rooty]
        elif self.rank[rootx] > self.rank[rooty]:
            self.parent[rooty] = rootx
            self.rank[rooty] = self.rank[rootx]
        else: 
            self.parent[rootx] = rooty
            self.rank[rooty] += 1
        self.count -= 1
    def connected(self,x,y):
        return self.find(x) == self.find(y)


class Solution:
    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        uf = UF(1001)
        for x,y in edges:
            if uf.connected(x,y):
                 return [x,y]
            uf.union(x,y)

并查集时间复杂度:O(NlogN)? 为什么不是logN

空间复杂度:O(1001)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值