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.
The hint provided by leetcode is:
Hints:
- 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:
典型的拓扑排序。原理也很简单,在一个有向图中,每次找到一个没有前驱节点的节点(也就是入度为0的节点),然后把它指向其他节点的边都去掉,重复这个过程(BFS),直到所有节点已被找到,或者没有符合条件的节点(如果图中有环存在)。
回顾一下图的三种表示方式:边表示法(即题目中表示方法),邻接表法,邻接矩阵。用邻接表存储图比较方便寻找入度为0的节点。
1 public class Solution { 2 public boolean canFinish(int numCourses, int[][] prerequisites) { 3 ArrayList<Integer>[] graph = new ArrayList[numCourses]; 4 int[] indegree = new int[numCourses]; 5 6 for (int i=0; i<numCourses; i++) { 7 graph[i] = new ArrayList<Integer>(); 8 } 9 10 for (int[] each : prerequisites) { 11 graph[each[0]].add(each[1]); 12 indegree[each[1]]++; 13 } 14 15 Queue<Integer> queue = new LinkedList<Integer>(); 16 for (int i=0; i<indegree.length; i++) { 17 if (indegree[i] == 0) { 18 queue.offer(i); 19 } 20 } 21 22 int count = 0; 23 while (!queue.isEmpty()) { 24 int cur = (int)queue.poll(); 25 count++; 26 27 for (int course : graph[cur]) { 28 indegree[course]--; 29 if (indegree[course] == 0) { 30 queue.offer(course); 31 } 32 } 33 } 34 return count == numCourses; 35 } 36 }
Better solution: Adjacent Matrix
1 public boolean canFinish(int numCourses, int[][] prerequisites) { 2 int[][] matrix = new int[numCourses][numCourses]; // i -> j 3 int[] indegree = new int[numCourses]; 4 5 for (int i=0; i<prerequisites.length; i++) { 6 int ready = prerequisites[i][0]; 7 int pre = prerequisites[i][1]; 8 if (matrix[pre][ready] == 0) 9 indegree[ready]++; //duplicate case 10 matrix[pre][ready] = 1; 11 } 12 13 int count = 0; 14 Queue<Integer> queue = new LinkedList(); 15 for (int i=0; i<indegree.length; i++) { 16 if (indegree[i] == 0) queue.offer(i); 17 } 18 while (!queue.isEmpty()) { 19 int course = queue.poll(); 20 count++; 21 for (int i=0; i<numCourses; i++) { 22 if (matrix[course][i] != 0) { 23 if (--indegree[i] == 0) 24 queue.offer(i); 25 } 26 } 27 } 28 return count == numCourses;