码迷,mamicode.com
首页 > 其他好文 > 详细

Leetcode: Course Schedule

时间:2015-12-16 12:24:36      阅读:136      评论:0      收藏: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.

The hint provided by leetcode is:

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.

My solution is vis DFS: (using HashSet)

 1 public class Solution {
 2     public boolean canFinish(int numCourses, int[][] prerequisites) {
 3         if (prerequisites.length==0 || prerequisites[0].length==0) return true;
 4         
 5         List<Set> posts = new ArrayList<Set>();
 6         for (int i = 0; i < numCourses; i++) {
 7             posts.add(new HashSet<Integer>());
 8         }
 9         
10         // fill the adjacency list
11         for (int i = 0; i < prerequisites.length; i++) {
12             posts.get(prerequisites[i][1]).add(prerequisites[i][0]);
13         }
14         
15         int[] visited = new int[numCourses];
16         for (int i=0; i<numCourses; i++) {
17             if (!canFinishDfs(i, posts, visited)) return false;
18         }
19         return true;
20     }
21     
22     public boolean canFinishDfs(int start, List<Set> posts, int[] visited) {
23         if(visited[start]==-1) 
24             return false;
25         if(visited[start]==1) 
26             return true;
27  
28         visited[start] = -1;
29         
30         Set<Integer> neighbors = posts.get(start);
31         Iterator<Integer> iter = neighbors.iterator();
32         while(iter.hasNext()) {
33             int neibor = iter.next();
34             if(!canFinishDfs(neibor, posts, visited)) 
35                 return false;
36         }
37         
38         visited[start] = 1;
39         
40         return true;
41     }
42 }

Another DFS solution using HashMap:

 1 public boolean canFinish(int numCourses, int[][] prerequisites) {
 2     if(prerequisites == null){
 3         throw new IllegalArgumentException("illegal prerequisites array");
 4     }
 5  
 6     int len = prerequisites.length;
 7  
 8     if(numCourses == 0 || len == 0){
 9         return true;
10     }
11  
12     //track visited courses
13     int[] visit = new int[numCourses];
14  
15     // use the map to store what courses depend on a course 
16     HashMap<Integer,ArrayList<Integer>> map = new HashMap<Integer,ArrayList<Integer>>();
17     for(int[] a: prerequisites){
18         if(map.containsKey(a[1])){
19             map.get(a[1]).add(a[0]);
20         }else{
21             ArrayList<Integer> l = new ArrayList<Integer>();
22             l.add(a[0]);
23             map.put(a[1], l);
24         }
25     }
26  
27     for(int i=0; i<numCourses; i++){
28         if(!canFinishDFS(map, visit, i))
29             return false;
30     }
31  
32     return true;
33 }
34  
35 private boolean canFinishDFS(HashMap<Integer,ArrayList<Integer>> map, int[] visit, int i){
36     if(visit[i]==-1) 
37         return false;
38     if(visit[i]==1) 
39         return true;
40  
41     visit[i]=-1;
42     if(map.containsKey(i)){
43         for(int j: map.get(i)){
44             if(!canFinishDFS(map, visit, j)) 
45                 return false;
46         }
47     }
48  
49     visit[i]=1;
50  
51     return true;
52 }

BFS: (refer: http://www.programcreek.com/2014/05/leetcode-course-schedule-java/)

典型的拓扑排序。原理也很简单,在一个有向图中,每次找到一个没有前驱节点的节点(也就是入度为0的节点),然后把它指向其他节点的边都去掉,重复这个过程(BFS),直到所有节点已被找到,或者没有符合条件的节点(如果图中有环存在)。

回顾一下图的三种表示方式:边表示法(即题目中表示方法),邻接表法,邻接矩阵。用邻接表存储图比较方便寻找入度为0的节点。

 1 public boolean canFinish(int numCourses, int[][] prerequisites) {
 2     if(prerequisites == null){
 3         throw new IllegalArgumentException("illegal prerequisites array");
 4     }
 5  
 6     int len = prerequisites.length;
 7  
 8     if(numCourses == 0 || len == 0){
 9         return true;
10     }
11  
12     // counter for number of prerequisites
13     int[] pCounter = new int[numCourses];
14     for(int i=0; i<len; i++){
15         pCounter[prerequisites[i][0]]++;
16     }
17  
18     //store courses that have no prerequisites
19     LinkedList<Integer> queue = new LinkedList<Integer>();
20     for(int i=0; i<numCourses; i++){
21         if(pCounter[i]==0){
22             queue.add(i);
23         }
24     }
25  
26     // number of courses that have no prerequisites
27     int numNoPre = queue.size();
28  
29     while(!queue.isEmpty()){
30         int top = queue.remove();
31         for(int i=0; i<len; i++){
32             // if a course‘s prerequisite can be satisfied by a course in queue
33             if(prerequisites[i][1]==top){
34                 pCounter[prerequisites[i][0]]--;
35                 if(pCounter[prerequisites[i][0]]==0){
36                     numNoPre++;
37                     queue.add(prerequisites[i][0]);
38                 }
39             }
40         }
41     }
42  
43     return numNoPre == numCourses;
44 }

 

Leetcode: Course Schedule

标签:

原文地址:http://www.cnblogs.com/EdwardLiu/p/5050550.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!