subject
Topic link: https://leetcode-cn.com/problems/course-schedule-ii
Now you have a total of N courses to choose, which are 0 to n-1.
Some prerequisite courses are required before taking some courses. For example, to learn lesson 0, you need to complete lesson 1 first. We use a match to represent them: [0,1]
Given the total number of courses and their prerequisites, return to the order in which you have arranged to complete all courses.
There may be multiple correct orders, you just need to return one. If it is not possible to complete all courses, an empty array is returned.
Penetration
Baidu Encyclopedia explains as follows
- When the degree of penetration is 0, the point in the digraph is not the end point of any edge, that is to say, the edge connected by this point takes this point as the starting point.
- In the topological sorting of digraphs, every time a point with a degree of entry of 0 is selected to join the topological queue, and then all the edges connected with this point are deleted.
Problem solving record
- Limited statistics of enrollment of each course
- Courses with entry degree of 0 are written into the queue
- Queue to get courses and write to the complete courses array
- Then reduce the enrollment of the course to 1. If the enrollment of the course to 1 is 0, join the queue
- Finally, judge whether the number of courses matches
import java.util.LinkedList; import java.util.Queue; /** * @author ffzs * @describe * @date 2020/5/17 */ public class findOrder { public int[] findOrder (int numCourses, int[][] prerequisites) { if (numCourses == 0) return prerequisites[0]; // Create entry table int[] indegree = new int[numCourses], res = new int[numCourses]; for (int[] pr: prerequisites) { indegree[pr[0]]++; } Queue<Integer> queue = new LinkedList<>(); for (int i = 0; i < indegree.length; i++) { if (indegree[i] == 0) queue.offer(i); } int count = 0; while (!queue.isEmpty()) { int index = queue.poll(); res[count++] = index; for (int[] pr: prerequisites) { if (pr[1] == index) { if (indegree[pr[0]] == 1) queue.offer(pr[0]); else indegree[pr[0]] --; } } } return count == numCourses? res: new int[0]; } }
Advanced
- In fact, it is faster to use depth search
- We can build a list to store the course relationship, similar to the figure below
- If there is no correlation, it will be put into the curriculum directly
- If there is an association, use recursion to judge whether the associated course can be completed
- In order to determine whether there is a circular state, we build three states:
- Not searched: 0
- Searching: 1
- Completion: - 1
- If there is a link in the course description in the search again, you can't go back to normal learning
class Solution { int[] step, res; int count = 0; ArrayList<Integer>[] adjacent; public int[] findOrder(int numCourses, int[][] prerequisites) { if (numCourses==0) return new int[0]; step = new int[numCourses]; res = new int[numCourses]; adjacent = new ArrayList[numCourses]; for (int i = 0; i < numCourses ; i++) adjacent[i] = new ArrayList<>(); for (int[] pr:prerequisites) adjacent[pr[0]].add(pr[1]); for (int i = 0; i < numCourses; i++) if (isCycle(i)) return new int[0]; return res; } public boolean isCycle (int i) { if (step[i]==1) return true; if (step[i]==-1) return false; step[i] = 1; for (int l: adjacent[i]) if (isCycle(l)) return true; res[count++] = i; step[i] = -1; return false; } }