https://leetcode.com/problems/course-schedule-ii/
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, return the ordering of courses you should take to finish all courses.
There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
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 the correct course order is [0,1]
4, [[1,0],[2,0],[3,1],[3,2]]
There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. So one correct course order is [0,1,2,3]
. Another correct ordering is[0,2,1,3]
.
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
解题思路:
BFS的解法,思路和上题相同。先统计好每一个节点的入度。入度为0的节点放入排序结果。
public class Solution { public int[] findOrder(int numCourses, int[][] prerequisites) { Queue<Integer> queue = new LinkedList<Integer>(); // 课程index的前置课程数量 int[] preNum = new int[numCourses]; int count = 0; int[] res = new int[numCourses]; for(int[] pair : prerequisites) { preNum[pair[0]]++; } for(int i = 0; i < numCourses; i++) { if(preNum[i] == 0) { queue.offer(i); res[count] = i; count++; } } while(queue.size() > 0) { int num = queue.poll(); for(int[] pair : prerequisites) { if(pair[1] == num) { preNum[pair[0]]--;//上了一节前置课程 if(preNum[pair[0]] == 0) {//只有当前置课程全部上了,该才能上该课程 queue.offer(pair[0]); res[count] = pair[0]; count++; } } } } if(count != numCourses) { return new int[]{}; } return res; } }
这道题和上道题一样,除了BFS的解法,同样有DFS。个人认为BFS无论是理解上,还是coding上,都要直接容易一点。
要注意的是,DFS出来的结果是倒序的。为什么?回忆一下DFS的过程,是不断的去处理下一节点。当前节点处理完毕后,标记为已遍历,就加入结果集。回弹到上一节点,再去处理上一节点的下一个出度。
所以这样的结果集一定是倒序的。
public class Solution { public int[] findOrder(int numCourses, int[][] prerequisites) { List<Integer> res = new ArrayList<Integer>(); Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>(); for(int[] pair : prerequisites) { if(map.containsKey(pair[1])) { List<Integer> list = map.get(pair[1]); list.add(pair[0]); } else { List<Integer> list = new ArrayList<Integer>(); list.add(pair[0]); map.put(pair[1], list); } } int[] visited = new int[numCourses]; for(int i = 0; i < numCourses; i++) { if(!dfs(map, res, visited, i)) { return new int[]{}; } } int[] result = new int[res.size()]; // 注意res出来的是倒序 for(int i = 0; i < res.size(); i++) { result[result.length - 1 - i] = res.get(i); } return result; } public boolean dfs(Map<Integer, List<Integer>> map, List<Integer> res, int[] visited, int step) { if(visited[step] == -1) { return false; } if(visited[step] == 1) { return true; } visited[step] = -1; List<Integer> list = map.get(step); if(list == null) { visited[step] = 1; res.add(step); return true; } for(Integer next : list) { if(!dfs(map, res, visited, next)) { return false; } } visited[step] = 1; res.add(step); return true; } }