From 9c15d18fab5db304d24adffca8536ea44a9089e7 Mon Sep 17 00:00:00 2001 From: tom4649 Date: Thu, 9 Jul 2026 06:21:31 +0900 Subject: [PATCH] Step1,2 --- 0210.Course-Schedule-II/memo.md | 20 +++++++++++ 0210.Course-Schedule-II/step1_dfs.py | 34 +++++++++++++++++++ 0210.Course-Schedule-II/step2_dfs_revised.py | 34 +++++++++++++++++++ 0210.Course-Schedule-II/step2_kahn.py | 29 ++++++++++++++++ 0210.Course-Schedule-II/step2_kahn_revised.py | 29 ++++++++++++++++ 5 files changed, 146 insertions(+) create mode 100644 0210.Course-Schedule-II/memo.md create mode 100644 0210.Course-Schedule-II/step1_dfs.py create mode 100644 0210.Course-Schedule-II/step2_dfs_revised.py create mode 100644 0210.Course-Schedule-II/step2_kahn.py create mode 100644 0210.Course-Schedule-II/step2_kahn_revised.py diff --git a/0210.Course-Schedule-II/memo.md b/0210.Course-Schedule-II/memo.md new file mode 100644 index 0000000..d9955f9 --- /dev/null +++ b/0210.Course-Schedule-II/memo.md @@ -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 +変数名を具体的にする diff --git a/0210.Course-Schedule-II/step1_dfs.py b/0210.Course-Schedule-II/step1_dfs.py new file mode 100644 index 0000000..f75a2ac --- /dev/null +++ b/0210.Course-Schedule-II/step1_dfs.py @@ -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] diff --git a/0210.Course-Schedule-II/step2_dfs_revised.py b/0210.Course-Schedule-II/step2_dfs_revised.py new file mode 100644 index 0000000..6c6d701 --- /dev/null +++ b/0210.Course-Schedule-II/step2_dfs_revised.py @@ -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] diff --git a/0210.Course-Schedule-II/step2_kahn.py b/0210.Course-Schedule-II/step2_kahn.py new file mode 100644 index 0000000..5e4be75 --- /dev/null +++ b/0210.Course-Schedule-II/step2_kahn.py @@ -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 + + diff --git a/0210.Course-Schedule-II/step2_kahn_revised.py b/0210.Course-Schedule-II/step2_kahn_revised.py new file mode 100644 index 0000000..7ff66bf --- /dev/null +++ b/0210.Course-Schedule-II/step2_kahn_revised.py @@ -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 + +