210. Course Schedule II
Medium
There are a total of n
courses you have to take labelled from 0
to n - 1
.
Some courses may have prerequisites
, for example, if prerequisites[i] = [ai, bi]
this means you must take the course bi
before the course ai
.
Given the total number of courses numCourses
and a list of the prerequisite
pairs, return the ordering of courses you should take to finish all courses.
If there are many valid answers, return any of them. If it is impossible to finish all courses, return an empty array.
Example 1:
Input: numCourses = 2, prerequisites = [[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: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]] Output: [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].
Example 3:
Input: numCourses = 1, prerequisites = [] Output: [0]
Constraints:
1 <= numCourses <= 2000
0 <= prerequisites.length <= numCourses * (numCourses - 1)
prerequisites[i].length == 2
0 <= ai, bi < numCourses
ai != bi
- All the pairs
[ai, bi]
are distinct.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | //C++: method1 740ms label the courses along the recursion class Solution { public: vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) { vector<int> label(numCourses), ret; bool visited[2000] = {false}; int cur_label = numCourses; for(int i=0; i<numCourses; ++i){ if(!visited[i]) dfs(i, prerequisites, visited, label, cur_label, ret); } for(auto p:prerequisites){ if(label[p.first]<label[p.second]){ return vector<int>(); } } reverse(ret.begin(), ret.end()); return ret; } void dfs(int course, vector<pair<int, int>>& prerequisites, bool *visited, vector<int> &label, int &cur_label, vector<int> &ret){ visited[course] = true; for(auto p:prerequisites){ if(course==p.second && !visited[p.first]){ dfs(p.first, prerequisites, visited, label, cur_label, ret); } } label[course] = --cur_label; ret.push_back(course); } }; //C++: method2 524ms standard dfs method using a stack #define NC 2000 class Solution { public: vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) { bool preqs[NC][NC] = {false}; for(auto p:prerequisites) preqs[p.second][p.first] = true; bool visited[NC] = {false}; bool path[NC] = {false}; stack<int> stk; vector<int> ret; for(int i=0; i<numCourses; ++i){ if(!visited[i]){ path[i] = true; if(hasCycle(numCourses, i, stk, preqs, visited, path)) return ret; path[i] = false; } } while(!stk.empty()){ ret.push_back(stk.top()); stk.pop(); } return ret; } bool hasCycle(int N, int node, stack<int> &stk, bool preqs[][NC], bool *visited, bool *path){ visited[node] = true; for(int i=0; i<N; ++i){ if(preqs[node][i]){ if(path[i]) return true; path[i] = true; if(!visited[i]) if(hasCycle(N, i, stk, preqs, visited, path)) return true; path[i] = false; } } stk.push(node); return false; } }; //C++: method3 620ms dfs method without a stack class Solution { public: vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) { vector<int> order; bool visited[numCourses]; memset(visited, false, numCourses*sizeof(bool)); bool path[numCourses]; memset(path, false, numCourses*sizeof(bool)); for(int i=0; i<numCourses; ++i){ path[i] = true; if(!visited[i] && hasCycle(numCourses, prerequisites, i, visited, path, order)){ order.clear(); return order; } path[i] = false; } reverse(order.begin(), order.end()); return order; } bool hasCycle(int numCourses, vector<pair<int, int>>& prerequisites, int curNode, bool *visited, bool *path, vector<int> &order){ visited[curNode] = true; for(auto p:prerequisites){ if(p.second==curNode){ if(path[p.first]) return true; if(!visited[p.first]){ path[p.first] = true; if(hasCycle(numCourses, prerequisites, p.first, visited, path, order)) return true; path[p.first] = false; } } } order.push_back(curNode); return false; } }; //Java class Solution { Set<Integer> path, visited; Map<Integer, Set<Integer>> preqs; List<Integer> schedule; public int[] findOrder(int numCourses, int[][] prerequisites) { path = new HashSet<>(); visited = new HashSet<>(); preqs = new HashMap<>(); schedule = new ArrayList<>(); for(int[] p : prerequisites){ preqs.computeIfAbsent(p[0], k -> new HashSet<Integer>()).add(p[1]); } for(int c = 0; c<numCourses; ++c){ path.add(c); if(!visited.contains(c) && hasCycle(c)) return new int[0]; path.remove(c); } int[] ret = new int[schedule.size()]; for(int i=0; i<schedule.size(); ++i) ret[i] = schedule.get(i); return ret; } boolean hasCycle(int course){ visited.add(course); if(preqs.containsKey(course)){ for(int p : preqs.get(course)){ if(path.contains(p)) return true; path.add(p); if(!visited.contains(p) && hasCycle(p)) return true; path.remove(p); } } schedule.add(course); return false; } } |
No comments:
Post a Comment