https://leetcode.com/problems/course-schedule/
关于graph的题目,考察拓扑排序
Course Schedule
这里只要判断是否能拓扑排序就行,就是看graph内有没有环,是不是DAG。
拓扑排序 参考http://blog.youkuaiyun.com/dm_vincent/article/details/7714519,
思路1 Kahn算法
http://songlee24.github.io/2015/05/07/topological-sorting/
思路很简单,
- 从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。
- 从图中删除该顶点和所有以它为起点的有向边。
- 重复 1 和 2 直到当前的 DAG 图为空或当前图中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。
这里就看当前图中是否存在无前驱的顶点就行。
code参考http://bookshadow.com/weblog/2015/05/07/leetcode-course-schedule/
class Solution:
# @param {integer} numCourses
# @param {integer[][]} prerequisites
# @return {boolean}
def canFinish(self, numCourses, prerequisites):
degrees = [0] * numCourses#记录indegree
childs = [[] for x in range(numCourses)]
for pair in prerequisites:
#这里的edge 是 pair[1] -> pair[0]
degrees[pair[0]] += 1
childs[pair[1]].append(pair[0])
courses = set(range(numCourses))
flag = True
while flag and len(courses):
flag = False
removeList = []
for x in courses:
if degrees[x] == 0:
for child in childs[x]:
degrees[child] -= 1
removeList.append(x)
flag = True
for x in removeList:
courses.remove(x)
return len(courses) == 0
思路2 DFS或者BFS
参考http://yucoding.blogspot.hk/2015/06/leetcode-question-course-schedule.html
没看太懂,再看看
自己复习重写
打算用入度出度两个dict来做,但是实际上这样的结构不方便
in_num = {}
out_num = {}
for x in prerequisites:
if x[0] not in in_num:
in_num[x[0]] = x[1]
else:
in_num[x[0]].append(x[1])
if x[1] not in out_num:
out_num[x[1]] = x[0]
else:
out_num[x[1]].append(x[0])
还是要按照ref的数据结构,用indegree和child就行。而且初始化每一个course对应的child node为[]
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
indegree = [0]*numCourses
child = [[] for x in range(numCourses)]#这里注意初始化方法,全部初始化为[]比较方便
for pair in prerequisites:
indegree[pair[0]] += 1
child[pair[1]].append(pair[0])
course = list(range(numCourses))#这里用list 就行
while len(course) > 0:
removelist = []#这里以免破坏course,在搜索完毕之后,一起remove掉
for x in course:
if indegree[x] == 0:
removelist.append(x)
for y in child[x]:
indegree[y] -= 1
if len(removelist) == 0:#即没有indegree为0的course了。所以要False
return False
for x in removelist:
course.remove(x)
return True
Course Schedule II
参考http://bookshadow.com/weblog/2015/05/14/leetcode-course-schedule-ii/
把拓扑排序的结果输出即可。
这里也有上述两种思路,DFS以及BFS的思路再看看。
自己重写的code
class Solution(object):
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
indegree = [0]*numCourses
child = [[] for x in range(numCourses)]#这里注意初始化方法,全部初始化为[]比较方便
for pair in prerequisites:
indegree[pair[0]] += 1
child[pair[1]].append(pair[0])
course = list(range(numCourses))#这里用list 就行
ans = []
while len(course) > 0:
removelist = []#这里以免破坏course,在搜索完毕之后,一起remove掉
for x in course:
if indegree[x] == 0:
removelist.append(x)
for y in child[x]:
indegree[y] -= 1
if len(removelist) == 0:#即没有indegree为0的course了。所以要False
return []
for x in removelist:
ans.append(x)
course.remove(x)
return ans