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.
public class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
ArrayList[] graph = new ArrayList[numCourses];
for(int i=0;i<numCourses;i++)
graph[i]= new ArrayList();
boolean[] visited = new boolean[numCourses];
for(int i=0;i<prerequisites.length;i++){
graph[prerequisites[i][1]].add(prerequisites[i][0]);
}
for(int i=0;i<numCourses;i++){
if(!dfs(graph,visited,i)) return false;
}
return true;
}
private boolean dfs(ArrayList[] graph, boolean[] visited, int course){
if(visited[course]) return false;
else visited[course] =true;
for(int i=0;i<graph[course].size();i++){
if(!dfs(graph,visited,(int)graph[course].get(i))) return false;
}
visited[course]=false;
return true;
}
}
总结:比较慢,最差o(n^2),设1-2-3,判断完1还得重新从2判断。106ms
private boolean dfs(ArrayList[] graph, boolean[] visited, int course){
if(visited[course]) return false;
else visited[course] =true;
for(int i=0;i<graph[course].size();i++){
if(!dfs(graph,visited,(int)graph[course].get(i))) return false;
graph[course].remove(i);
i--;
}
visited[course]=false;
return true;
}
总结:其他没有变,增加了remove,去掉判断过的边,记得要加i--。因为remove之后index会变化。5ms
private boolean dfs(ArrayList[] graph, boolean[] visited, int course){
if(visited[course]) return false;
else visited[course] =true;
for(int i=0;i<graph[course].size();i++){
if(!dfs(graph,visited,(int)graph[course].get(i))) return false;
iteratorDelete(graph[course].iterator(),i);
}
visited[course]=false;
return true;
}
private void iteratorDelete(Iterator<Integer> it, int deleteObject){
while(it.hasNext()){
int i = it.next();
if(i==deleteObject){
it.remove();
}
}
}
总结:利用Iterator进行删除,index发生变化,但是加入了while循环,231秒。
public class Solution {
public boolean canFinish(int num, int[][] mat) {
Map<Integer, Set<Integer>> dependOn = new HashMap<>();
for (int[] edge : mat) {
int child = edge[0];
int parent = edge[1];
dependOn.putIfAbsent(child, new HashSet<Integer>());
dependOn.get(child).add(parent);
}
boolean[] visited = new boolean[num];
boolean[] onStack = new boolean[num];
for (int i = 0; i < num; i++) {
if (!visited[i]) { // find one not visited and start from it
if (!dfs(dependOn, i, visited, onStack))
return false;
}
}
return true;
}
public boolean dfs(Map<Integer, Set<Integer>> dependOn, int current, boolean[] visited, boolean[] onStack) {
onStack[current] = true; // mark current on the stack of a post-order traversal
for (int parent : dependOn.getOrDefault(current, new HashSet<Integer>())) {
if (onStack[parent]) // one of the dependency is still not popped from the stack
return false;
if (!visited[parent] && !dfs(dependOn, parent, visited, onStack))
return false;
}
visited[current] = true; // can also be placed before visiting children, so place is not important
onStack[current] = false; // making DFS a post-order traversal: popping current when all its children are done
return true;
}
}
总结:设置了一个onstack,如果之后的子链true的话设置true。
public class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] adj = new List[numCourses];
for(int i = 0; i < numCourses; i++)
adj[i] = new ArrayList<Integer>();
int[] indegree = new int[numCourses];
Queue<Integer> readyCourses = new LinkedList();
int finishCount = 0;
for (int i = 0; i < prerequisites.length; i++)
{
int curCourse = prerequisites[i][0];
int preCourse = prerequisites[i][1];
adj[preCourse].add(curCourse);
indegree[curCourse]++;
}
for (int i = 0; i < numCourses; i++)
{
if (indegree[i] == 0)
readyCourses.offer(i);
}
while (!readyCourses.isEmpty())
{
int course = readyCourses.poll(); // finish
finishCount++;
for (int nextCourse : adj[course])
{
indegree[nextCourse]--;
if (indegree[nextCourse] == 0)
readyCourses.offer(nextCourse); // ready
}
}
return finishCount == numCourses;
}
}
总结:把所有可以修的课程放入队列中,9ms