Open In App

Course Schedule I

Last Updated : 22 Oct, 2025
Comments
Improve
Suggest changes
70 Likes
Like
Report

Given courses, labeled from 0 to n - 1 and an array prerequisites[] where prerequisites[i] = [x, y] indicates that we need to take course y first if we want to take course x.

Find if it is possible to complete all tasks. Return true if all tasks can be completed, or false if it is impossible.

Examples:

Input: n = 4, prerequisites = [[2, 0], [2, 1], [3, 2]]
Output: true
Explanation: To take course 2, you must first finish courses 0 and 1.
To take course 3, you must first finish course 2.
All courses can be completed, for example in the order [0, 1, 2, 3] or [1, 0, 2, 3].

Input: n = 3, prerequisites = [[0, 1], [1, 2], [2, 0]]
Output: false
Explanation: To take course 0, you must first finish course 1.
To take course 1, you must first finish course 2.
To take course 2, you must first finish course 0.
Since each course depends on the other, it is impossible to complete all courses.

[Approach 1] Using DFS for Cycle Detection

We can think of each course as a node in a directed graph, and each prerequisite pair [a, b] as a directed edge from b → a.

This means:

  • To take course a, you must complete course b first.
  • So, there is a directed edge from b (the prerequisite) to a (the dependent course).

Once this graph is built, we need to check if there is any cycle in the graph, because:

  • If a cycle exists, it is impossible to finish all courses, as some courses would depend on each other in a loop.
  • If no cycle exists, it is possible to complete all courses, since a valid ordering of courses can be obtained by visiting prerequisites before dependent courses.

 Now we can detect cycle using DFS, where we track each node’s state to detect cycles.

C++
#include <iostream>
#include <vector>

using namespace std;

// DFS to detect cycle
bool dfs(int node, vector<vector<int>>& adj, vector<int>& visited) {
    
    // mark as visiting
    visited[node] = 1; 

    for (int neighbor : adj[node]) {
        if (visited[neighbor] == 1) {
            
            // cycle detected
            return false; 
        } else if (visited[neighbor] == 0) {
            if (!dfs(neighbor, adj, visited)) {
            
                return false; 
            }
        }
    }
    
    // mark as visited
    visited[node] = 2; 
    return true;
}

// Function to check if all courses can be completed
bool canFinish(int n, vector<vector<int>>& prerequisites) {
    vector<vector<int>> adj(n);
    for (auto& pre : prerequisites) {
        int dest = pre[0];
        int src = pre[1];
        adj[src].push_back(dest);
    }
    
    // 0 = unvisited, 1 = visiting, 2 = visited
    vector<int> visited(n, 0); 

    for (int i = 0; i < n; i++) {
        if (visited[i] == 0) {
            if (!dfs(i, adj, visited)) {
                
                // cycle detected
                return false; 
            }
        }
    }
    
    return true;
}

int main() {
    int n = 4;
    vector<vector<int>> prerequisites = { {2, 0}, {2, 1}, {3, 2} };

    cout << (canFinish(n, prerequisites) ? "true" : "false") << endl;

    return 0;
}
Java
import java.util.ArrayList;

class GFG {
    
    // DFS to detect cycle
    static boolean dfs(int node, ArrayList<ArrayList<Integer>> adj, int[] visited) {
      
        // mark as visiting
        visited[node] = 1;
        
        for (int neighbor : adj.get(node)) {
            if (visited[neighbor] == 1) {
                // cycle detected
                return false;
            } else if (visited[neighbor] == 0) {
                if (!dfs(neighbor, adj, visited)) {
                    return false;
                }
            }
        }
        
        // mark as visited
        visited[node] = 2;
        return true;
    }

    // Function to check if all courses can be completed
    static boolean canFinish(int n, int[][] prerequisites) {
        ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            adj.add(new ArrayList<>());
        }
        for (int[] pre : prerequisites) {
            int dest = pre[0];
            int src = pre[1];
            adj.get(src).add(dest);
        }
        
        // 0 = unvisited, 1 = visiting, 2 = visited
        int[] visited = new int[n];
        
        for (int i = 0; i < n; i++) {
            if (visited[i] == 0) {
                if (!dfs(i, adj, visited)) {
                    // cycle detected
                    return false;
                }
            }
        }
        
        return true;
    }

    public static void main(String[] args) {
        int n = 4;
        int[][] prerequisites = { {2, 0}, {2, 1}, {3, 2} };
        
        System.out.println(canFinish(n, prerequisites) ? "true" : "false");
    }
}
Python
from typing import List


# DFS to detect cycle
def dfs(node, adj, visited):

    # mark as visiting
    visited[node] = 1
        
    for neighbor in adj[node]:
        if visited[neighbor] == 1:

            # cycle detected
            return False
        elif visited[neighbor] == 0:
            if not dfs(neighbor, adj, visited):
                return False
        
    # mark as visited
    visited[node] = 2
    return True

# Function to check if all courses can be completed
def canFinish(n, prerequisites) -> bool:
    adj = [[] for _ in range(n)]
    for dest, src in prerequisites:
        adj[src].append(dest)
    
    # 0 = unvisited, 1 = visiting, 2 = visited
    visited = [0] * n
        
    for i in range(n):
        if visited[i] == 0:
            if not dfs(i, adj, visited):

                # cycle detected
                return False
        
    return True

if __name__ == "__main__":
    n = 4
    prerequisites = [[2, 0], [2, 1], [3, 2]]
    
    print("true" if canFinish(n, prerequisites) else "false")
C#
using System;
using System.Collections.Generic;

class GFG {
    
    // DFS to detect cycle
    static bool dfs(int node, List<List<int>> adj, int[] visited) {
        
        // mark as visiting
        visited[node] = 1;
        
        foreach (int neighbor in adj[node]) {
            if (visited[neighbor] == 1) {
                
                // cycle detected
                return false;
            } 
            else if (visited[neighbor] == 0) {
                if (!dfs(neighbor, adj, visited)) {
                    return false;
                }
            }
        }
        
        // mark as visited
        visited[node] = 2;
        return true;
    }

    // Function to check if all courses can be completed
    static bool canFinish(int n, int[,] prerequisites) {
        List<List<int>> adj = new List<List<int>>();
        for (int i = 0; i < n; i++) {
            adj.Add(new List<int>());
        }
        
        int m = prerequisites.GetLength(0);
        for (int i = 0; i < m; i++) {
            int dest = prerequisites[i, 0];
            int src = prerequisites[i, 1];
            adj[src].Add(dest);
        }
        
        // 0 = unvisited, 1 = visiting, 2 = visited
        int[] visited = new int[n];
        
        for (int i = 0; i < n; i++) {
            if (visited[i] == 0) {
                if (!dfs(i, adj, visited)) {
                    
                    // cycle detected
                    return false;
                }
            }
        }
        
        return true;
    }

    public static void Main(string[] args) {
        
        int n = 4;
        int[,] prerequisites = { {2, 0}, {2, 1}, {3, 2} };
        
        Console.WriteLine(canFinish(n, prerequisites) ? "true" : "false");
    }
}
JavaScript
// DFS to detect cycle
function dfs(node, adj, visited) {
        
    // mark as visiting
    visited[node] = 1;
        
    for (let neighbor of adj[node]) {
        if (visited[neighbor] === 1) {
    
            // cycle detected
                return false;
        } else if (visited[neighbor] === 0) {
            if (!dfs(neighbor, adj, visited)) {
                return false;
            }
        }
    }
        
    // mark as visited
    visited[node] = 2;
    return true;
}

// Function to check if all courses can be completed
function canFinish(n, prerequisites) {
    let adj = Array.from({ length: n }, () => []);
    for (let pre of prerequisites) {
        let dest = pre[0];
        let src = pre[1];
        adj[src].push(dest);
    }
        
    // 0 = unvisited, 1 = visiting, 2 = visited
    let visited = Array(n).fill(0);
        
    for (let i = 0; i < n; i++) {
        if (visited[i] === 0) {
            if (!dfs(i, adj, visited)) {
    
                // cycle detected
                return false;
            }
        }
    }
        
    return true;
}

// Driver Code
const n = 4;
const prerequisites = [[2, 0], [2, 1], [3, 2]];

console.log(canFinish(n, prerequisites) ? 'true' : 'false');

Output
true

Time Complexity: O(V+E), where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V+E)

[Approach 2] Using Topological Sorting

If we perform a topological sort and all the nodes get visited, then it means there is no cycle and it is possible to finish all the tasks. If any of the node is unvisited, it means that particular node is dependent on another node which in turn is dependent on some other node and so on. So, we cannot finish those tasks because of circular dependency.

C++
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

bool canFinish(int n, vector<vector<int>>& prerequisites) {
    vector<vector<int>> graph(n);
    vector<int> inDegree(n, 0);
   
    for (auto& pre : prerequisites) {
        int dest = pre[0];
        int src = pre[1];
        graph[src].push_back(dest);
        inDegree[dest]++;
    }

    queue<int> q;
    
    // Push all the nodes with no dependencies
    // (indegree = 0)
    for (int i = 0; i < n; i++)
        if (inDegree[i] == 0)
            q.push(i);

    while (!q.empty()) {
        int node = q.front(); q.pop();
        for (int child : graph[node]) {
            inDegree[child]--;
            
            // Push the neighboring node if we have covered
            // all its dependencies (indegree = 0)
            if (inDegree[child] == 0)
                q.push(child);
        }
    }
    
    // Check if there is a node whose indegree is not zero
    for (int i = 0; i < n; i++)
        if (inDegree[i] != 0)
            return false;

    return true;
}

int main() {
    int n = 4;
    vector<vector<int>> prerequisites = { {2, 0}, {2, 1}, {3, 2} };

    cout << (canFinish(n, prerequisites) ? "true" : "false") << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;
import java.util.Queue;

class GFG {
    static boolean canFinish(int n, int[][] prerequisites) {
        List<List<Integer>> graph = new ArrayList<>();
        int[] inDegree = new int[n];

        for (int i = 0; i < n; i++)
            graph.add(new ArrayList<>());

        for (int[] pre : prerequisites) {
            int dest = pre[0];
            int src = pre[1];
            graph.get(src).add(dest);
            inDegree[dest]++;
        }

        Queue<Integer> q = new LinkedList<>();

        // Push all the nodes with no dependencies (indegree = 0)
        for (int i = 0; i < n; i++)
            if (inDegree[i] == 0)
                q.add(i);

        while (!q.isEmpty()) {
            int node = q.poll();
            for (int child : graph.get(node)) {
                inDegree[child]--;

                // Push the neighboring node if 
                // we have covered all its dependencies (indegree = 0)
                if (inDegree[child] == 0)
                    q.add(child);
            }
        }

        // Check if there is a node whose indegree is not zero
        for (int i = 0; i < n; i++)
            if (inDegree[i] != 0)
                return false;

        return true;
    }

    public static void main(String[] args) {
        int n = 4;
        int[][] prerequisites = { {2, 0}, {2, 1}, {3, 2} };

        System.out.println(canFinish(n, prerequisites) ? "true" : "false");
    }
}
Python
from collections import deque

def canFinish(n, prerequisites):
    graph = [[] for _ in range(n)]
    inDegree = [0] * n

    for dest, src in prerequisites:
        graph[src].append(dest)
        inDegree[dest] += 1

    q = deque()

    # Push all the nodes with no dependencies (indegree = 0)
    for i in range(n):
        if inDegree[i] == 0:
            q.append(i)

    while q:
        node = q.popleft()
        for child in graph[node]:
            inDegree[child] -= 1

            # Push the neighboring node
            # if we have covered all its dependencies (indegree = 0)
            if inDegree[child] == 0:
                q.append(child)

    # Check if there is a node whose indegree is not zero
    for i in range(n):
        if inDegree[i] != 0:
            return False

    return True

if __name__ == '__main__':
    n = 4
    prerequisites = [[2, 0], [2, 1], [3, 2]]
    print("true" if canFinish(n, prerequisites) else "false")
C#
using System;
using System.Collections.Generic;

class GFG {
    static bool canFinish(int n, int[,] prerequisites) {
        List<List<int>> graph = new List<List<int>>();
        int[] inDegree = new int[n];

        for (int i = 0; i < n; i++)
            graph.Add(new List<int>());

        int m = prerequisites.GetLength(0);
        for (int i = 0; i < m; i++) {
            int dest = prerequisites[i, 0];
            int src = prerequisites[i, 1];
            graph[src].Add(dest);
            inDegree[dest]++;
        }

        Queue<int> q = new Queue<int>();

        // Push all the nodes with no dependencies (indegree = 0)
        for (int i = 0; i < n; i++)
            if (inDegree[i] == 0)
                q.Enqueue(i);

        while (q.Count > 0) {
            int node = q.Dequeue();
            foreach (int child in graph[node]) {
                inDegree[child]--;

                // Push the neighboring node if all dependencies are covered
                if (inDegree[child] == 0)
                    q.Enqueue(child);
            }
        }

        // Check if there is a node whose indegree is not zero
        for (int i = 0; i < n; i++)
            if (inDegree[i] != 0)
                return false;

        return true;
    }

    public static void Main() {
        int n = 4;
        int[,] prerequisites = { {2, 0}, {2, 1}, {3, 2} };

        Console.WriteLine(canFinish(n, prerequisites) ? "true" : "false");
    }
}
JavaScript
const Denque = require("denque");

function canFinish(n, prerequisites) {
    const graph = Array.from({ length: n }, () => []);
    const inDegree = Array(n).fill(0);

    for (const [dest, src] of prerequisites) {
        graph[src].push(dest);
        inDegree[dest]++;
    }

    const q = new Denque();

    // Push all the nodes with no dependencies (indegree = 0)
    for (let i = 0; i < n; i++)
        if (inDegree[i] === 0)
            q.push(i);

    while (!q.isEmpty()) {
        const node = q.shift();
        for (const child of graph[node]) {
            inDegree[child]--;

            // Push the neighboring node if all dependencies are covered
            if (inDegree[child] === 0)
                q.push(child);
        }
    }

    // Check if there is a node whose indegree is not zero
    for (let i = 0; i < n; i++)
        if (inDegree[i] !== 0)
            return false;

    return true;
}

// Driver code
const n = 4;
const prerequisites = [[2, 0], [2, 1], [3, 2]];

console.log(canFinish(n, prerequisites) ? "true" : "false");

Output
true

Time Complexity: O(V+E), where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V)


Explore