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