Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions 0210.Course-Schedule-II/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 210. Course Schedule II

## step1
最初集合で先祖を管理しようとしたが、閉路検出ができないことに気づき、statusを使う方針に書き換えた。
19mほど。

## 他の人のコードなど

> DFSのトポロジカルソートですが、preorder(行きがけ)でTEMPORARYとマークか、すでにTEMPORARYなら、サイクルと判定。postorder(帰りがけ)でPERMANENTとマークするみたいな感じですね。

https://github.com/potrue/leetcode/pull/77/changes

入次数で管理するやり方。Kahnのアルゴリズムというものだった。他の問題で見た覚えがあるが使えなかった。

https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%9D%E3%83%AD%E3%82%B8%E3%82%AB%E3%83%AB%E3%82%BD%E3%83%BC%E3%83%88

Kahnのアルゴリズムを書くのはBFS, DFSどちらでも可能だがBFSで実装する。

## step2
変数名を具体的にする
34 changes: 34 additions & 0 deletions 0210.Course-Schedule-II/step1_dfs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class Solution:
def findOrder(self, numCourses: int, prerequisites: list[list[int]]) -> list[int]:
adjacent_list = [[] for _ in range(numCourses)]
for second, first in prerequisites:
adjacent_list[first].append(second)

order = []
# 0: 未訪問, 1: 訪問中, 2: 訪問ずみ
status = [0] * numCourses

def dfs(i):
if status[i] == 1:
return False
if status[i] == 2:
return True

status[i] = 1
for j in adjacent_list[i]:
can_be_finished = dfs(j)
if not can_be_finished:
return False

status[i] = 2
order.append(i)
return True

for i in range(numCourses):
if status[i] != 0:
continue
can_be_finished = dfs(i)
if not can_be_finished:
return []

return order[::-1]
34 changes: 34 additions & 0 deletions 0210.Course-Schedule-II/step2_dfs_revised.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class Solution:
def findOrder(self, numCourses: int, prerequisites: list[list[int]]) -> list[int]:
next_courses = [[] for _ in range(numCourses)]
for second, first in prerequisites:
next_courses[first].append(second)

order = []
# 0: 未訪問, 1: 訪問中, 2: 訪問ずみ
status = [0] * numCourses

def dfs(course):
if status[course] == 1:
return False
if status[course] == 2:
return True

status[course] = 1
for next_course in next_courses[course]:
can_be_finished = dfs(next_course)
if not can_be_finished:
return False

status[course] = 2
order.append(course)
return True

for course in range(numCourses):
if status[course] != 0:
continue
can_be_finished = dfs(course)
if not can_be_finished:
return []

return order[::-1]
29 changes: 29 additions & 0 deletions 0210.Course-Schedule-II/step2_kahn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import collections

class Solution:
def findOrder(self, numCourses: int, prerequisites: list[list[int]]) -> list[int]:
adjacent_list = [[] for _ in range(numCourses)]
in_degree = [0] * numCourses
for second, first in prerequisites:
adjacent_list[first].append(second)
in_degree[second] += 1

queue = collections.deque()
for i in range(numCourses):
if in_degree[i] == 0:
queue.append(i)

order = []
while queue:
i = queue.popleft()
order.append(i)
for j in adjacent_list[i]:
in_degree[j] -= 1
if in_degree[j] == 0:
queue.append(j)

if len(order) != numCourses:
return []
return order


29 changes: 29 additions & 0 deletions 0210.Course-Schedule-II/step2_kahn_revised.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import collections

class Solution:
def findOrder(self, numCourses: int, prerequisites: list[list[int]]) -> list[int]:
next_courses = [[] for _ in range(numCourses)]
in_degree = [0] * numCourses
for second, first in prerequisites:
next_courses[first].append(second)
in_degree[second] += 1

available_courses = collections.deque()
for course in range(numCourses):
if in_degree[course] == 0:
available_courses.append(course)

order = []
while available_courses:
course = available_courses.popleft()
order.append(course)
for next_course in next_courses[course]:
in_degree[next_course] -= 1
if in_degree[next_course] == 0:
available_courses.append(next_course)

if len(order) != numCourses:
return []
return order