鉴于课程数量及其先决条件,我必须返回学生可以参加课程的正确顺序,即学生如果没有完成课程就不能参加课程。 -requisite。请参阅以下样本输入和输出以进行说明
课程顺序
示例输入:
- 课程数量:4
- 先决条件清单:[[1,2],[3,2],[2,4]]
// [i,j]表示我是先决条件
输出:[1,3,2,4]
或[3,1,2,4]
示例输入:
- 课程数量:2
- 先决条件清单:[[1,2],[2,1]]
输出:[]
//由于循环依赖性而没有可能的解决方案
这是我天真的解决方案:
class Solution:
def __init__(self):
self.order = []
self.mapping = {}
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
for pre_req in prerequisites:
if pre_req[1] not in self.mapping:
self.mapping[pre_req[1]] = [pre_req[0]]
else:
self.mapping[pre_req[1]].append(pre_req[0])
# for i in range(1, numCourses+1):
# if i not in self.mapping:
# self.order.append(i)
j = 0
# for key in self.mapping:
# i += 1
# if key not in self.order:
# self.helper(key, i)
# break
for i in range(1, numCourses+1):
if i in self.mapping:
self.helper(i, j)
return self.order
def helper(self, key, i):
if len(self.mapping[key]) == 0:
if key not in self.order:
self.order.append(key)
for ki in self.mapping:
if key in self.mapping[ki]:
self.mapping[k].remove(value)
self.mapping.pop(key, None)
return
for k in self.mapping:
for value in self.mapping[k]:
if value not in self.mapping:
if value not in self.order:
self.order.append(value)
for ki in self.mapping:
if value in self.mapping[ki]:
self.mapping[k].remove(value)
else:
self.mapping[k].remove(value)
else:
self.helper(k, i+1)
if len(self.mapping[key]) == 0:
if key not in self.order:
self.order.append(key)
for ki in self.mapping:
if key in self.mapping[ki]:
self.mapping[k].remove(value)
s = Solution()
prereq = [[1,2],[3,2],[2,4]]
courses = 4
res = s.canFinish(courses, prereq)
print(res)
4
[[1,2],[3,2],[2,4]]
=============================更新============== ==================
key
字典中mapping
的值,并且是先决条件,即值作为不同的在mapping
字典中键入然后我在self.order
中添加,我正在递归地执行此操作mapping = {course1 : [prereq1, prereq2], course2: [prereq1, prereq3]}
mapping
是否有prereq1
作为键,然后将prereq1
的值添加到self.order
答案 0 :(得分:2)
这是topological sorting的经典用例。如果您将先决条件视为有向图,其中存在从先决条件到另一个课程的边缘,您可以简单地找到图形的拓扑类型,您将获得答案。当图形具有循环时,未定义拓扑排序,类似地,您的课程不应具有循环,因为您永远无法参加这些课程。在python中,您可以使用简单的深度优先搜索进行拓扑排序,跟踪进入和退出节点的时间。退出节点时(在查看所有子节点之后),将该节点添加到列表中。例如:
from collections import defaultdict
graph = defaultdict(set)
def getCourses(prereq):
for p in prereq:
# build a simple graph structure: keys are node value is a set of children
graph[p[1]]
graph[p[0]].add(p[1])
visited = set()
seen = set()
courses = []
def dfs(node): # depth-first search
if node in visited: return
if node in seen:
raise ValueError("Error cycle in prerequisites")
seen.add(node)
for e in graph[node]:
dfs(e) #recurse on children
seen.remove(node)
visited.add(node)
courses.insert(0, node)
for k in graph.keys():
if k in visited:
continue
try: dfs(k)
except ValueError: # in case of cycle
return []
return courses
print(getCourses([[1,2],[3,2],[2,4]]))
答案 1 :(得分:1)
这是我的解决方案。我跟踪这个对象的课程:
class Course():
'''A course object. Holds a pre-req, maybe'''
def __init__(self, id):
self.id = id
self.reqs = []
def add_req(self, course):
self.reqs.append(course)
def has_req(self):
return len(self.reqs) > 0
def reqs_satisfied(self, path):
return set(self.reqs).issubset(set(path))
因此,如果有任何课程,我可以查看其要求。
我只对将所有课程添加到列表中感兴趣,遵循以下规则:
如果无法添加课程,那是因为我们找不到满足先决条件的方法(在这种情况下,当存在循环先决条件时,因为我们不会让自己进入循环)
这意味着
class Solution():
def __init__(self, course_data, prereq_data):
'''Create courses, and fill in pre-reqs'''
self.courses = {}
for id in course_data:
self.courses[id] = Course(id)
# [i, j], assuming course i is the pre-req for course j
for data in prereq_data:
pre_req = self.courses[data[0]]
course = self.courses[data[1]]
course.add_req(pre_req)
def build_path(self):
all_courses = list(self.courses.values())
num_courses = len(all_courses)
path = []
# Add each course recursively
while len(all_courses) > 0:
course = all_courses.pop(0)
self.add_course(course, path, [])
# Check if the path is valid (ie: all courses are taken)
if len(path) == num_courses:
return path
else:
return []
def add_course(self, course, path, visited):
# ignore courses that have already been added.
# also, ignore courses that have been visited already (avoid cycle)
if course in path or course in visited:
return
visited.append(course)
# if this course has requirement, add it. Possible that we don't add it
for req in course.reqs:
self.add_course(req, path, visited)
# try adding this course, after pre-reqs have been checked.
if (course.reqs_satisfied(path)):
path.append(course)
path = Solution([1,2,3,4], [[1,2],[3,2],[2,4]]).build_path()
print("Solution: ", [course.id for course in path])
path = Solution([2,1,7,4], []).build_path()
print("Solution: ", [course.id for course in path])
答案 2 :(得分:0)
from collections import defaultdict
class CourseSelection(object):
def __init__(self):
self.num_of_courses = 0
self.prereq_map = defaultdict(list)
self.seen = set()
self.is_cycle = False
def add_prereq(self, parent, prereq):
self.num_of_courses += 1
self.prereq_map[parent].append(prereq)
def topological_util(self, courses_order, visited, node):
if self.is_cycle:
return
self.seen.add(node)
for prereq in self.prereq_map[node]:
if prereq in self.seen:
print("Cycle Found")
self.is_cycle = True
return True
if prereq not in visited:
visited.add(prereq)
self.topological_util(courses_order, visited, prereq)
self.seen.remove(node)
courses_order.append(node)
def topological_sort(self, start_node):
visited = set([])
courses_order = []
for i in range(self.num_of_courses):
# print(i, visited)
if i not in visited:
visited.add(i)
self.topological_util(courses_order, visited, i)
print(courses_order)
cs = CourseSelection()
cs.add_prereq(5, 0)
cs.add_prereq(5, 2)
# g.add_prereq(2, 5)
cs.add_prereq(2, 3)
cs.add_prereq(3, 1)
cs.add_prereq(4, 0)
cs.add_prereq(4, 1)
cs.topological_sort(0)