Tuesday, August 25, 2015

Course Schedule | Leetcode

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.


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.
---

Solution: The hints tells us that there are 3 possible algorithms to solve this problem. I personally find the finding cycles in a directed graph algorithm the simplest to understand, so that is what I have here.
public class Solution {
    private static class Course {
        private boolean seen;
        private boolean inRecursionStack;
        private List<Course> prerequisites = new ArrayList<>();
    
        private boolean hasCycle() {
            if (seen) return false;
            if (inRecursionStack) return true;
            
            inRecursionStack = true;
            
            for (Course prereq: prerequisites) {
                if (prereq.hasCycle()) return true;
            }
            
            inRecursionStack = false;
            seen = true;
            return false;
        }
    }
    
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        // Create all course objects.
        Course[] courses = new Course[numCourses];
        for (int i = 0; i < numCourses; i++) {
            courses[i] = new Course();
        }
        
        // Add all course prerequisites.
        for (int[] prereq: prerequisites) {
            Course course1 = courses[prereq[0]];
            Course course2 = courses[prereq[1]];
            course1.prerequisites.add(course2);
        }
        
        // Check for cycles.
        for (Course course: courses) {
            if (course.hasCycle()) return false;
        }
        
        return true;
    }
}

No comments: