Skip to content

Commit 6541b17

Browse files
committed
Solution: Course Schedule
1 parent 79f42eb commit 6541b17

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

course-schedule/flynn.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
풀이
3+
- 각 course를 node로 생각하고, prerequisite 관계에 있는 node를 간선으로 이어주면 단방향 간선으로 연결된 node 집합의 graph를 떠올릴 수 있습니다
4+
- 이 문제는 위에서 설명한 graph에 loop가 있냐 없느냐를 판단하는 문제입니다
5+
- 함수의 재귀호출 및 백트래킹을 이용해서 풀이할 수 있습니다
6+
7+
Big O
8+
- N: 과목 수 (node의 개수)
9+
- M: 배열 prerequisites의 길이 (간선의 개수)
10+
- Time compleixty: O(N + M)
11+
- prereqMap을 초기화 -> O(M)
12+
- 함수의 재귀호출을 통해 우리는 각 node를 최대 한번씩 조회합니다 -> O(N)
13+
- Space complexity: O(N + M)
14+
- prereqMap -> O(M)
15+
- checkingSet, checkedSet -> O(N)
16+
*/
17+
18+
func canFinish(numCourses int, prerequisites [][]int) bool {
19+
// 주어진 prerequisites 배열로 `a_i: b_0, b_1, ...` 형태의 맵을 짭니다
20+
prereqMap := make(map[int][]int, numCourses)
21+
for _, pair := range prerequisites {
22+
prereqMap[pair[0]] = append(prereqMap[pair[0]], pair[1])
23+
}
24+
25+
// checkingSet으로 현재 탐색하고 있는 구간에 loop가 생겼는지 여부를 판단하고, checkedSet으로 이미 탐색한 node인지를 판단합니다
26+
checkingSet, checkedSet := make(map[int]bool, 0), make(map[int]bool, 0)
27+
28+
// 특정 과목 c를 듣기 위한 선행 과목들을 탐색했을 때 loop가 생기는지 여부를 판단하는 함수입니다
29+
// (Go 언어 특성상 L:20-21 처럼 함수를 선언합니다 (함수 내부에서 함수를 선언할 땐 익명 함수를 사용 + 해당 함수를 재귀호출하기 위해서 선언과 초기화를 분리))
30+
var checkLoop func(int) bool // loop가 있다면 true
31+
checkLoop = func(c int) bool {
32+
// 과목 c가 현재 탐색하고 있는 구간에 존재한다면 loop가 있다고 판단 내릴 수 있습니다
33+
_, checkingOk := checkingSet[c]
34+
if checkingOk {
35+
return true
36+
}
37+
// 과목 c가 이미 탐색이 완료된 과목이라면 과목 c를 지나는 하위 구간에는 loop가 없다고 판단할 수 있습니다
38+
_, checkedOk := checkedSet[c]
39+
if checkedOk {
40+
return false
41+
}
42+
// 과목 c를 checkingSet에 추가합니다
43+
// 만약 하위 구간에서 과목 c를 다시 만난다면 loop가 있다고 판단할 수 있습니다
44+
checkingSet[c] = true
45+
// 각 선행과목 별로 하위구간을 만들어 탐색을 진행합니다
46+
// 하위구간 중 하나라도 loop가 발생하면 현재 구간에는 loop가 있다고 판단할 수 있습니다
47+
for _, prereq := range prereqMap[c] {
48+
if checkLoop(prereq) {
49+
return true
50+
}
51+
}
52+
// 만약 loop가 발견되지 않았다면 checkedSet에 과목 c를 추가함으로써 과목 c를 지나는 구간이 안전하다고 표시합니다
53+
checkedSet[c] = true
54+
// checkingSet에서 과목 c를 지워줍니다
55+
delete(checkingSet, c)
56+
return false
57+
}
58+
59+
for i := 0; i < numCourses; i++ {
60+
if checkLoop(i) {
61+
return false
62+
}
63+
}
64+
return true
65+
}

0 commit comments

Comments
 (0)