207. Course Schedule**

188 篇文章 0 订阅
10 篇文章 0 订阅

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.

click to show more hints.

Hints:
  1. 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.
  2. Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
  3. Topological sort could also be done via BFS.  

DFS:
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。
The usual algorithms for topological sorting have running time linear in the number of nodes plus the number of edges, asymptotically,  {\displaystyle O(\left|{V}\right|+\left|{E}\right|)}O(\left|{V}\right|+\left|{E}\right|)

BFS:
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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值