题目描述
你这个学期必须选修 numCourses
门课程,记为 0
到 numCourses - 1
。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
- 例如,先修课程对
[0, 1]
表示:想要学习课程 0
,你需要先完成课程 1
。
请你判断是否可能完成所有课程的学习?如果可以,返回 true
;否则,返回 false
。
示例 1:
- 输入:numCourses = 2, prerequisites = [[1,0]]
- 输出:true
- 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:
- 输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
- 输出:false
- 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
- 0 <= ai, bi < numCourses
prerequisites[i]
中的所有课程对 互不相同
解法一:DFS + 记忆化搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
func canFinish(numCourses int, prerequisites [][]int) bool {
grid := make([][]bool, numCourses)
for i := 0; i < numCourses; i++ {
grid[i] = make([]bool, numCourses)
}
for _, pair := range prerequisites {
grid[pair[0]][pair[1]] = true
}
// visited[i] 有如下三种值
// 0: 还未检查该课程能否学习完
// 1: 打算学习该课程或该课程不能学习完
// 2: 该课程已学习完
visited := make([]int, numCourses)
// check 检查编号为 id 的课程是否可以学习完
var check func(id int) bool
check = func(id int) bool {
if visited[id] == 1 {
return false
} else if visited[id] == 2 {
return true
}
// 先假设本课程不能学习完,防止有环
visited[id] = 1
for j := 0; j < numCourses; j++ {
if grid[id][j] && !check(j) {
// 如果 j 是 id 的先行课程且 j 不能够学习完,则当前课程不可能学习完,直接返回 false。
// visited[id] = 1
return false
}
}
visited[id] = 2
return true
}
for id := 0; id < numCourses; id++ {
if !check(id) {
return false
}
}
return true
}
|
解法二:BFS