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)