207 Course Schedule
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. You may assume that there are no duplicate edges in the input prerequisites. click to show more hints. 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.
思路
先修课程是拓扑排序的经典应用, 这里相当于找有向图是否有环, 如果有环的话拓扑排序能遍历到的节点将少于图的节点. 这里我们建立一个图, 用一个数组记录每个节点的入度. 对图进行拓扑排序
复杂度
时间O(V+E) 空间 O(V)
public boolean canFinish(int numCourses, int[][] prerequisites) { if (prerequisites == null || prerequisites.length == 0 || prerequisites[0].length == 0) { return true; } //记录入度 int[] indgree = new int[numCourses]; //记录有向图的指向节点 ArrayList[] graph = new ArrayList[numCourses]; for (int i = 0; i < numCourses; i++) { graph[i] = new ArrayList<Integer>(); } //写入有向图的next节点 for (int i = 0; i < prerequisites.length; i++) { graph[prerequisites[i][1]].add(prerequisites[i][0]); indgree[prerequisites[i][0]]++; } Queue<Integer> queue = new LinkedList<Integer>(); for(int i = 0; i < indgree.length; i++){ if(indgree[i] == 0){ queue.add(i); } } int count = 0; while (!queue.isEmpty()) { int cur = queue.poll(); count++; ArrayList<Integer> list = graph[cur]; for (Integer tem : list) { indgree[tem]--; if (indgree[tem] == 0) { queue.offer(tem); } } } return count == numCourses; }
有向图: 入度和边, 用什么容器, 怎么生成图, 根据什么入队, 出队后怎么遍历其他的边, 并判断入队,
题意的分解:拓扑排序,BFS
难点--边的生成容器:
//记录有向图的指向节点 ArrayList[] graph = new ArrayList[numCourses]; for (int i = 0; i < numCourses; i++) { graph[i] = new ArrayList<Integer>(); }
生成图的容器 要有且明确是谁的:
1键值对, 且值是容器比如ArrayList[], hashmap<键, ArrayList<jian>())
2入度: int[], Arraylist.size()?