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?
Note:
The input is represented by a list of edges, not adjacency matrices or list.
You may assume that there are no duplicate edges in the input prerequisites.
Example:
1 2 3 4 5 6 7 8 9 10
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.
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.
DFS (Cycle Detection)
This problem is equivalent to finding if a cycle exists in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
My mistake: Using only true/false marked array does not solve the problem. We need more information because we are not dealing with a problem like finding a cycle in a path.
publicbooleancanFinish(int numCourses, int[][] preReq) { if (numCourses == 0 || preReq == null || preReq.length == 0) { returntrue; // or false } // convert to adjacency list O(E) List<List<Integer>> graph = newArrayList<>(); for (intv=0; v < numCourses; ++v) graph.add(newArrayList<>()); // init for (int[] edge : preReq) { graph.get(edge[1]).add(edge[0]); } // dfs int[] marked = newint[numCourses]; for (intv=0; v < numCourses; ++v) { // O(V) if (dfs(v, graph, marked)) returnfalse; // O(E) in total } returntrue; // no cycle -> can finish }
// Returns true if a cycle is detected. privatebooleandfs(int v, List<List<Integer>> graph, int[] marked) { // not visited: 0 | being visited: -1 | visited: +1 marked[v] = -1; // visit // for each neighbor for (int w : graph.get(v)) { if (marked[w] == -1) returntrue; // cycle exists if (marked[w] == 0) { // not visited if (dfs(w, graph, marked)) returntrue; } } marked[v] = +1; // visited returnfalse; // no cycle is detected }
Time: $O(V + E)$ Space: $O(V)$
BFS (Topological Sort)
The problem can be reduced to the one that finds if there is a topological sort in the graph (also equivalent to the one that finds if the graph is acyclic).
There are two ways of finding a topological sort: Reversed DFS and BFS. We pick BFS at this time.
The basic idea is that we add all nodes with 0 degrees into a queue, and do BFS from these nodes. They are the starting nodes in a graphs.
Each time we poll a node from the queue, we decrease all its neighbors’ in-degree by one. This is like deleting the node from the graph and removing all its outgoing edges. If a topological sort exists, we can remove the whole graph!
The whole process takes $O(V)$ steps in total if there is a topological sort.
So we need a count variable to check how many steps we have along this process. If it finally reduces to 0, then there is a topological sort.