[leetcode] Course Schedule


Course Schedule

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.

Topological sort BFS approach

  • for all node p in graph:
    • if p has no incoming edges:
      • push p in queue
  • while queue is not empty:
    • p = queue.front()
    • queue.pop()
    • for all v, v is p’s neighbor:
      • remove edge between p and v
      • if v has no incoming edges:
        • push v into queue
  • if graph has edges:
    • return error (exists circle)
  • else:
    • has no circle

Topological sort DFS approach

sort(graph g)

  • set all nodes as unmarked
  • for all un-permanent marked node v in graph:
    • visit(v)

visit(node v)

  • if v is temporally marked:
    • return false (circle exists)
  • if v is not permanently marked:
    • temporally mark v
    • for all neighbors q of v:
      • visit(q)
    • un temporally mark v
    • permanent mark v

 

class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        //[0, numCourses - 1]
        //topological sort.
        vector<int> incomingNum(numCourses, 0);
        vector<vector<int> > graph(numCourses, vector<int>());
        queue<int> q;
        //construct directed graph using edges
        for(auto edge : prerequisites){
            incomingNum[edge.first]++;
            graph[edge.second].push_back(edge.first);
        }
        
        //find all nodes whoes incomingNum is 0
        for(int i = 0; i < numCourses; i++){
            if(incomingNum[i] == 0){
                q.push(i);
             }
        }
        
        while(!q.empty()){
            int idx = q.front();
            q.pop();
            //find all neighbours, remove edges
            //if incomingNum of the neighbour is 0, push it into queue
            vector<int> neighbours = graph[idx];
            for(auto neighbour: neighbours){
                incomingNum[neighbour]--;
                if(incomingNum[neighbour] == 0){
                    q.push(neighbour);
                }
            }
            graph[idx].clear();
        }
        //if there are still some edges remain, cicle exists
        for(auto node: graph){
            if(!node.empty()) return false;
        }
        return true;
        
    }
};

 

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.