返回
Python轻松搞定LeetCode 207:课程表(DFS+BFS)
后端
2023-10-17 04:29:32
前言
在计算机科学中,图论是一个重要的分支,它主要研究图的结构和性质。图论在许多领域都有着广泛的应用,例如网络、通信、交通、社交网络等。在LeetCode上,图论题目也经常出现,考察的内容包括图的遍历、最短路径、最小生成树等。
LeetCode 207:课程表
LeetCode 207:课程表是一道经典的图论算法题,考察图中是否有环的问题。题目如下:
你需要设计一个课程表,使每门课只能在所有依赖它的课程结束后才能开课。请你判断是否能够满足这个要求,并给出课表的顺序。
解题思路
要解决这个问题,我们可以将课程之间的依赖关系表示成一个有向图。然后,我们可以使用DFS或BFS来遍历这个有向图。如果在遍历过程中检测到环,则说明课程表无法满足要求。否则,我们可以根据遍历结果输出课程的顺序。
DFS解法
DFS(Depth-First Search,深度优先搜索)是一种图的遍历算法,它通过沿着一条路径深度搜索,直到无法继续深入时才回溯到前一个节点继续搜索。DFS解法的步骤如下:
- 将所有课程初始化为未访问状态。
- 选择一个课程作为起点,开始DFS遍历。
- 在DFS过程中,如果遇到一个课程已经被访问过,则说明存在环,返回False。
- 如果在DFS过程中,所有课程都已经被访问过,则说明不存在环,返回True。
def canFinish_dfs(numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
# Create an adjacency list representation of the graph.
adj_list = [[] for _ in range(numCourses)]
for course, prereq in prerequisites:
adj_list[prereq].append(course)
# Initialize the visited and stack arrays.
visited = [False] * numCourses
stack = []
# Perform DFS on each unvisited node.
for i in range(numCourses):
if not visited[i]:
if dfs(i, adj_list, visited, stack):
return False
# If there is no cycle, return True.
return True
def dfs(node, adj_list, visited, stack):
"""
Perform DFS on the given node.
:param node: The current node.
:param adj_list: The adjacency list representation of the graph.
:param visited: The array of visited nodes.
:param stack: The stack of nodes that have been visited.
:return: True if a cycle is detected, False otherwise.
"""
# Mark the node as visited.
visited[node] = True
# Push the node onto the stack.
stack.append(node)
# Visit all the neighbors of the node.
for neighbor in adj_list[node]:
# If the neighbor has not been visited, perform DFS on it.
if not visited[neighbor]:
if dfs(neighbor, adj_list, visited, stack):
return True
# If the neighbor is already in the stack, a cycle has been detected.
elif neighbor in stack:
return True
# Pop the node from the stack.
stack.pop()
# Return False to indicate that no cycle has been detected.
return False
BFS解法
BFS(Breadth-First Search,广度优先搜索)也是一种图的遍历算法,它通过一层一层地遍历图中的所有节点,直到将所有节点都访问过。BFS解法的步骤如下:
- 将所有课程初始化为未访问状态。
- 将所有课程的入度初始化为0。
- 将所有入度为0的课程加入队列。
- 从队列中取出一个课程,并将其标记为已访问。
- 对于该课程的所有邻接课程,将它们的入度减1。
- 如果某个邻接课程的入度变为0,则将其加入队列。
- 重复步骤4-6,直到队列为空。
def canFinish_bfs(numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
# Create an adjacency list representation of the graph.
adj_list = [[] for _ in range(numCourses)]
for course, prereq in prerequisites:
adj_list[prereq].append(course)
# Initialize the in-degree array.
in_degree = [0] * numCourses
for course, prereq in prerequisites:
in_degree[course] += 1
# Initialize the queue with all courses that have in-degree 0.
queue = [i for i in range(numCourses) if in_degree[i] == 0]
# While there are still courses in the queue, process them.
while queue:
# Get the first course in the queue.
course = queue.pop(0)
# Mark the course as visited.
in_degree[course] -= 1
# For each neighbor of the course, decrement its in-degree.
for neighbor in adj_list[course]:
in_degree[neighbor] -= 1
# If a neighbor's in-degree becomes 0, add it to the queue.
if in_degree[neighbor] == 0:
queue.append(neighbor)
# If all courses have been visited, return True.
return all(in_degree[i] == 0 for i in range(numCourses))
复杂度分析
DFS和BFS解法的复杂度都为O(V+E),其中V是课程的数量,E是依赖关系的数量。
总结
LeetCode 207:课程表是一道经典的图论算法题,考察图中是否有环的问题。我们使用DFS和BFS两种方法来解决这个问题,并提供了详细的Python代码和注释。希望这篇文章对大家有所帮助!