파이썬 알고리즘 인터뷰 문제 39번(리트코드 207번) Course Schedule
https://leetcode.com/problems/course-schedule/
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = collections.defaultdict(list)
result = [True]
for a, b in prerequisites:
graph[a].append(b)
graph[b]
#for x in graph:
# print(graph[x])
def helper(course, path):
#print(course, path, result)
if not graph[course]:
return
for prerequisite in graph[course]:
if prerequisite in path:
result[0] = False
#print('a', course, path, result)
return
else:
path.append(prerequisite)
helper(prerequisite, path)
path.pop()
for course in graph:
helper(course, [])
return result[0]
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = collections.defaultdict(list)
for a, b in prerequisites:
graph[b].append(a) # b -> a
visited = [0] * numCourses # 0: 방문 안 함, 1: 방문 중, 2: 방문 완료
def has_cycle(course):
if visited[course] == 1: # 사이클 발견
return True
if visited[course] == 2: # 이미 방문 완료
return False
visited[course] = 1 # 현재 방문 중 표시
for neighbor in graph[course]:
if has_cycle(neighbor):
return True
visited[course] = 2 # 방문 완료 표시
return False
for course in range(numCourses):
if has_cycle(course):
return False
return True
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = collections.defaultdict(list)
trace = set()
visited = set()
for a, b in prerequisites:
graph[a].append(b)
def has_cycle(course):
if course in trace:
return True
if course in visited:
return False
trace.add(course)
for neighbor in graph[course]:
if has_cycle(neighbor):
return True
# 오답1. return has_cycle(neighbor) 하면 안됨.
trace.remove(course)
visited.add(course)
return False
for course in list(graph): # 오답2. 그냥 graph로 에러 발생.
if has_cycle(course):
return False
return True
if has_cycle(neighbor) then return True대신 return has_cycle(neighbor)하면 틀린다.1-> [2, 3]2-> []3 -> [1]1↔3으로 cycle이 있다.1 이웃으로 2를 검사하게 되고 2는 이웃이 없으므로 False를 반환하게 된다. 그러면 1 도 False를 반환하게 된다. 하지만 1 은 이웃 3 과 cycle을 이룬다. 이는 1의 이웃인 2, 3을 모두 검사하기 전에 2 만 검사하고 False를 반환하기 때문이다.cycle 발견되었을 때는 나머지 이웃을 검사하지 않고 True를 반환하면 되지만, cycle 없다고 하려면 모든 이웃을 검사해야 한다.for course in graph로 순회하면 RuntimeError: dictionary changed size during iteration 에러 발생graph[a]=b 와 같은 방법으로 생성했으므로, b 는 key로 없을 수 있다. 이때, defaultdict으로 생성했으므로 graph[b]를 하는 순간 빈 리스트로 초기화 되어 graph의 key가 하나 늘어난다. for문으로 순회하며 key가 늘어나기 때문에 이런 에러가 발생한다. 이런 일이 일어나는 것은 has_cycle(neighbor) 에서 neighbor이 key로 없기 때문이다.list(graph) 로 key를 list로 복사하여 순회하는 방법이 있고, 그래프를 생성할 때, 아래와 같이 graph[a].append(b) 와 graph[b]를 모두 하는 방법이 있다. for a, b in prerequisites:
graph[a].append(b)
graph[b] # <- 미리 초기화하여 두기.