210. Course Schedule II
- tags
- Topological Ordering, BFS, DFS, Graph
- source
- leetcode
Edge Cases
Solution 1 - Topological Ordering, BFS
class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new ArrayList<List<Integer>>();
int[] incomingNums = new int[numCourses];
// init graph
for (int i = 0; i < numCourses; i++) {
graph.add(new ArrayList<Integer>());
}
for (int i = 0; i < prerequisites.length; i++) {
int[] edge = prerequisites[i];
graph.get(edge[1]).add(edge[0]);
incomingNums[edge[0]]++;
}
// bfs
Queue<Integer> queue = new LinkedList<Integer>();
int[] results = new int[numCourses];
int curr = 0;
for (int i = 0; i < numCourses; i++) {
if (incomingNums[i] == 0) queue.add(i);
}
while (!queue.isEmpty()) {
int from = queue.poll();
results[curr++] = from;
for (int to: graph.get(from)) {
incomingNums[to]--;
if (incomingNums[to] == 0) queue.add(to);
}
}
return curr == numCourses ? results : new int[0];
}
}
Complexity
- time: O(V+E)
- space: O(V+E)
Solution 2 - DFS
class Solution {
static int WHITE = 1;
static int GRAY = 2;
static int BLACK = 3;
boolean isPossible;
Map<Integer, Integer> color;
Map<Integer, List<Integer>> adjList;
List<Integer> topologicalOrder;
private void init(int numCourses) {
this.isPossible = true;
this.color = new HashMap<Integer, Integer>();
this.adjList = new HashMap<Integer, List<Integer>>();
this.topologicalOrder = new ArrayList<Integer>();
// By default all vertces are WHITE
for (int i = 0; i < numCourses; i++) {
this.color.put(i, WHITE);
}
}
private void dfs(int node) {
// Don't recurse further if we found a cycle already
if (!this.isPossible) {
return;
}
// Start the recursion
this.color.put(node, GRAY);
// Traverse on neighboring vertices
for (Integer neighbor : this.adjList.getOrDefault(node, new ArrayList<Integer>())) {
if (this.color.get(neighbor) == WHITE) {
this.dfs(neighbor);
} else if (this.color.get(neighbor) == GRAY) {
// An edge to a GRAY vertex represents a cycle
this.isPossible = false;
}
}
// Recursion ends. We mark it as black
this.color.put(node, BLACK);
this.topologicalOrder.add(node);
}
public int[] findOrder(int numCourses, int[][] prerequisites) {
this.init(numCourses);
// Create the adjacency list representation of the graph
for (int i = 0; i < prerequisites.length; i++) {
int dest = prerequisites[i][0];
int src = prerequisites[i][1];
List<Integer> lst = adjList.getOrDefault(src, new ArrayList<Integer>());
lst.add(dest);
adjList.put(src, lst);
}
// If the node is unprocessed, then call dfs on it.
for (int i = 0; i < numCourses; i++) {
if (this.color.get(i) == WHITE) {
this.dfs(i);
}
}
int[] order;
if (this.isPossible) {
order = new int[numCourses];
for (int i = 0; i < numCourses; i++) {
order[i] = this.topologicalOrder.get(numCourses - i - 1);
}
} else {
order = new int[0];
}
return order;
}
}