leetcode刷題筆記-topological sort拓撲排序(DFS)
207. Course Schedule 找環
There are a total of n courses you have to take, labeled from 0
to n-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
Example 1:
Input: 2, [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: 2, [[1,0],[0,1]] Output: false Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
思路:找是否存在環,已經訪問完的標記為1,正在訪問的標記為2,如果遇到正在訪問的就是遇到環
class Solution(object): def canFinish(self, numCourses, prerequisites): """ :type numCourses: int :type prerequisites: List[List[int]] :rtype: bool """ mark = collections.defaultdict(int) prere = collections.defaultdict(list) for c, p in prerequisites: prere[c].append(p) def dfs(course): if mark[course] == 1: # visited return True if mark[course] == 2: # visiting return False # unvisited mark[course] = 2 # mark as visiting preCourses = prere[course] if preCourses == []: mark[course] = 1 return True else: for preCourse in preCourses: re = dfs(preCourse) if not re: return False mark[course] = 1 # mark as visited return True for course, pre in prerequisites: re = dfs(course) if not re: return False return True
210. Course Schedule II 拓撲排序
There are a total of n courses you have to take, labeled from 0
to n-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.
There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
Example 1:
Input: 2, [[1,0]] Output:[0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is[0,1] .
Example 2:
Input: 4, [[1,0],[2,0],[3,1],[3,2]] Output:[0,1,2,3] or [0,2,1,3]
Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. So one correct course order is[0,1,2,3]
. Another correct ordering is[0,2,1,3] .
class Solution(object):
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
self.graph = collections.defaultdict(list)
self.res = []
for c, p in prerequisites:
self.graph[c].append(p)
self.visited = [0 for x in xrange(numCourses)]
for node in xrange(numCourses):
if not self.DFS(node):
return []
return self.res
def DFS(self, node):
if self.visited[node] == -1: # visiting
return False
if self.visited[node] == 1: # visited and add to res
return True
self.visited[node] = -1 # mark as visiting
for x in self.graph[node]:
if not self.DFS(x):
return False
self.visited[node] = 1
self.res.append(node)
return True
269. Alien Dictionary
class Solution(object):
def alienOrder(self, words):
# a ->b
adj = collections.defaultdict(set)
# 入度
degree = {c: 0 for w in words for c in w}
for i, w1 in enumerate(words[:-1]):
w2 = words[i+1]
for c1, c2 in zip(w1, w2):
if c1 == c2:
continue
if c2 not in adj[c1]:
adj[c1].add(c2)
degree[c2] += 1
break # 需要break 因為word1, word2 比較,e.x. za,zb 比較的是 a和b。 而ab , ca 比較的是a和c, 和 b,a無關
res = ''
# start w 0 indegree nodes
q = [c for c in degree if not degree[c]]
while q:
c = q.pop(0)
res += c
for n in adj[c]:
degree[n] -= 1
if degree[n] == 0:
q.append(n)
return res if len(res) == len(degree) else ''