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?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
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.
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
- 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.
- Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
- Topological sort could also be done via BFS.
------------------------------------------------------------------------------
BFS: 先扫一遍数组,找到没有prerequisites的课程,加入到queue里 (没有prerequisites的课程就是我们可以完成的课程)。
在来对queue里的数进行处理,知道找到所有可以完成的课程。 比较其与numCourses的大小。
1 public class Solution { 2 // BFS VERSION 3 public boolean canFinish(int numCourses, int[][] prerequisites) { 4 int[] pCounter = new int[numCourses]; 5 for(int[] temp: prerequisites) { 6 pCounter[temp[0]]++; 7 } 8 Queue<Integer> noPre = new LinkedList<Integer>(); 9 for(int i = 0; i < pCounter.length; ++i) { 10 if(pCounter[i] == 0) 11 noPre.offer(i); 12 } 13 int res = noPre.size(); 14 while(!noPre.isEmpty()) { 15 int cur = noPre.poll(); 16 for(int[] temp: prerequisites) { 17 if(temp[1] == cur) { 18 pCounter[temp[0]]--; 19 if(pCounter[temp[0]] == 0) { 20 noPre.add(temp[0]); 21 res++; 22 } 23 } 24 } 25 } 26 return res == numCourses; 27 } 28 }
DFS:
与BFS去找没有pre-node的节点方法不同,DFS是利用:这个点作为prerequisite,我接下来可以选择哪些node来处理的。
在这里,我们需要用一个boolean的数组来判断这个node我们之前有没有访问过,如果访问过了,说明有cycle。
1 // DFS VERSION 2 public boolean canFinish(int numCourses, int[][] prerequisites) { 3 ArrayList[] nodes = new ArrayList[numCourses]; 4 for(int i = 0; i < numCourses; ++i) { 5 nodes[i] = new ArrayList<Integer>(); 6 } 7 for(int[] temp: prerequisites) { 8 nodes[temp[1]].add(temp[0]); 9 } 10 boolean[] visited = new boolean[numCourses]; 11 for(int i = 0; i < numCourses; ++i) { 12 if(!canFinish(nodes, visited ,i)) 13 return false; 14 } 15 return true; 16 } 17 public boolean canFinish(ArrayList[] nodes, boolean[] visited, int curIndex) { 18 if(visited[curIndex]) 19 return false; 20 visited[curIndex] = true; 21 ArrayList<Integer> curNeighbors = nodes[curIndex]; 22 for(int next: curNeighbors) { 23 if(!canFinish(nodes, visited, next)) 24 return false; 25 } 26 visited[curIndex] = false; 27 return true; 28 }