你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。 请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
时间: 2024-03-25 15:41:44 浏览: 189
计算机课程先修关系
这是一个典型的图论问题,我们可以使用拓扑排序来解决。拓扑排序的基本思想是将有向图中的所有顶点排成一个线性序列,使得图中任意一对顶点 $u$ 和 $v$,若边 $(u, v)$ 存在于图中,那么在序列中 $u$ 出现在 $v$ 的前面。具体做法是:
1. 统计每个节点的入度(即有多少条边指向它)。
2. 将所有入度为 0 的节点加入队列。
3. 循环执行以下操作,直到队列为空:
- 从队列中取出一个节点,将答案数组中对应位置标记为已访问。
- 将该节点的所有邻接节点的入度减 1。
- 如果邻接节点的入度为 0,将邻接节点加入队列。
4. 如果答案数组中所有位置均被标记为已访问,则说明可以完成所有课程的学习;否则,无法完成所有课程的学习。
下面是代码实现:
```python
def canFinish(numCourses, prerequisites):
in_degree = [0] * numCourses
adj_list = [[] for _ in range(numCourses)]
for a, b in prerequisites:
in_degree[a] += 1
adj_list[b].append(a)
queue = [i for i in range(numCourses) if in_degree[i] == 0]
visited = 0
while queue:
node = queue.pop(0)
visited += 1
for neighbor in adj_list[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
return visited == numCourses
```
其中,`in_degree` 用于存储每个节点的入度,`adj_list` 用于存储每个节点的邻接节点,`visited` 表示已经访问的节点数。首先,我们遍历 `prerequisites` 数组,统计每个节点的入度,并构建邻接表。然后,将所有入度为 0 的节点加入队列。接下来,不断从队列中取出节点,将其标记为已访问,并将其邻接节点的入度减 1。如果邻接节点的入度变为 0,则将其加入队列。最后,如果所有节点都被标记为已访问,则说明可以完成所有课程的学习。
阅读全文