|
1 | | -###207. Course Schedule |
| 1 | +# 207. Course Schedule |
2 | 2 |
|
| 3 | +**<font color=red>难度: Medium</font>** |
3 | 4 |
|
| 5 | +## 刷题内容 |
4 | 6 |
|
5 | | -题目: |
6 | | -<https://leetcode.com/problems/course-schedule/> |
| 7 | +> 原题连接 |
7 | 8 |
|
| 9 | +* https://leetcode.com/problems/course-schedule/description/ |
8 | 10 |
|
9 | | -难度: |
10 | | -Medium |
| 11 | +> 内容描述 |
11 | 12 |
|
12 | | -思路: |
| 13 | +``` |
| 14 | +There are a total of n courses you have to take, labeled from 0 to n-1. |
13 | 15 |
|
14 | | -就是考topological sort,用来判断directed graph是否有cycle |
| 16 | +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] |
15 | 17 |
|
16 | | -DFS 和 BFS都可以用来拓扑排序。 |
| 18 | +Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses? |
| 19 | +
|
| 20 | +Example 1: |
17 | 21 |
|
18 | | -最简单的想法是每次取出indegree是0的node,然后把它和与之相关的edge都删了。一开始觉得这样的时间复杂度会很高,然后看到了这样写,参照: |
| 22 | +Input: 2, [[1,0]] |
| 23 | +Output: true |
| 24 | +Explanation: There are a total of 2 courses to take. |
| 25 | + To take course 1 you should have finished course 0. So it is possible. |
| 26 | +Example 2: |
19 | 27 |
|
20 | | -<http://bookshadow.com/weblog/2015/05/07/leetcode-course-schedule/> |
| 28 | +Input: 2, [[1,0],[0,1]] |
| 29 | +Output: false |
| 30 | +Explanation: There are a total of 2 courses to take. |
| 31 | + To take course 1 you should have finished course 0, and to take course 0 you should |
| 32 | + also have finished course 1. So it is impossible. |
| 33 | +Note: |
21 | 34 |
|
22 | | -很聪明的写法 |
| 35 | +The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. |
| 36 | +You may assume that there are no duplicate edges in the input prerequisites. |
| 37 | +``` |
23 | 38 |
|
24 | | -这里做了转成set以及添加removeList这样的操作是因为边list边做iterator这样的操作很危险 |
| 39 | +## 解题方案 |
25 | 40 |
|
| 41 | +> 思路 1 |
| 42 | +******- 时间复杂度: O(V+E)******- 空间复杂度: O(N)****** |
| 43 | +[Topological sorting](https://www.geeksforgeeks.org/topological-sorting/) for Directed Acyclic Graph (DAG) is a linear ordering of vertices such that for every directed edge uv, vertex u comes before v in the ordering. Topological Sorting for a graph is not possible if the graph is not a DAG. |
26 | 44 |
|
| 45 | +pre-requisite问题,只需要判断最终的topological结果长度与courses数目是否相等即可 |
27 | 46 |
|
| 47 | +DFS 和 BFS都可以用来拓扑排序。 |
28 | 48 |
|
29 | | -``` |
| 49 | +beats 95.38% |
| 50 | +```python |
30 | 51 | class Solution(object): |
31 | 52 | def canFinish(self, numCourses, prerequisites): |
32 | 53 | """ |
33 | 54 | :type numCourses: int |
34 | 55 | :type prerequisites: List[List[int]] |
35 | 56 | :rtype: bool |
36 | 57 | """ |
37 | | - degrees = [ 0 for i in range(numCourses)] |
38 | | - childs = [[] for i in range(numCourses)] |
39 | | - for front, tail in prerequisites: |
40 | | - degrees[front] += 1 |
41 | | - childs[tail].append(front) |
42 | | -
|
43 | | - courses = set(range(numCourses)) |
44 | | - flag = True |
45 | | -
|
46 | | - while flag and len(courses): |
47 | | - flag = False |
48 | | - removeList = [] |
49 | | - for x in courses: |
50 | | - if degrees[x] == 0: |
51 | | - for child in childs[x]: |
52 | | - degrees[child] -= 1 |
53 | | - removeList.append(x) |
54 | | - flag = True |
55 | | - for x in removeList: |
56 | | - courses.remove(x) |
57 | | - return len(courses) == 0 |
58 | | -
|
| 58 | + graph = collections.defaultdict(list) |
| 59 | + indegrees = [0] * numCourses |
| 60 | + |
| 61 | + for course, pre in prerequisites: |
| 62 | + graph[pre].append(course) |
| 63 | + indegrees[course] += 1 |
| 64 | + |
| 65 | + return self.topologicalSort(graph, indegrees) == numCourses |
| 66 | + |
| 67 | + |
| 68 | + def topologicalSort(self, graph, indegrees): |
| 69 | + count = 0 |
| 70 | + queue = [] |
| 71 | + for i in range(len(indegrees)): |
| 72 | + if indegrees[i] == 0: |
| 73 | + queue.append(i) |
| 74 | + while queue: |
| 75 | + course = queue.pop() |
| 76 | + count += 1 |
| 77 | + for i in graph[course]: |
| 78 | + indegrees[i] -= 1 |
| 79 | + if indegrees[i] == 0: |
| 80 | + queue.append(i) |
| 81 | + return count |
59 | 82 | ``` |
60 | 83 |
|
61 | | -因为CLRS里面明确提到涂色法来处理DFS |
62 | 84 |
|
63 | | -搞了半天,写了一个涂色法,在超时的边缘。之所以超时边缘是因为每次都要去prerequisites里看,没有删减,不高效. |
64 | 85 |
|
65 | | -``` |
66 | | -class Solution(object): |
67 | | - def canFinish(self, numCourses, prerequisites): |
68 | | - """ |
69 | | - :type numCourses: int |
70 | | - :type prerequisites: List[List[int]] |
71 | | - :rtype: bool |
72 | | - """ |
73 | | - def dfs(i, colors, prerequisites): |
74 | | - colors[i] = 'G' |
75 | | - #print i, colors |
76 | | - for front, tail in prerequisites: |
77 | | - if tail == i: |
78 | | - if colors[front] == 'G': |
79 | | - return False |
80 | | - elif colors[front] == 'B': |
81 | | - continue |
82 | | - elif dfs(front, colors, prerequisites) == False: |
83 | | - return False |
84 | | - colors[i] = 'B' |
85 | | - return True |
86 | | -
|
87 | | - colors = ['W' for i in range(numCourses)] |
88 | | - for i in range(numCourses): |
89 | | - if colors[i] == 'W': |
90 | | - if dfs(i, colors, prerequisites) == False: |
91 | | - return False |
92 | | - return True |
93 | | -``` |
| 86 | + |
| 87 | + |
| 88 | + |
| 89 | + |
| 90 | + |
0 commit comments