|
| 1 | +--- |
| 2 | +id: course-schedule-II |
| 3 | +title: Course Schedule II |
| 4 | +sidebar_label: 0210 Course Schedule II |
| 5 | +tags: |
| 6 | +- Depth-First Search |
| 7 | +- Topological Sort |
| 8 | +- Graph |
| 9 | +- Breadth-First Search |
| 10 | +description: "This document provides a solution to the Course Schedule II problem." |
| 11 | +--- |
| 12 | + |
| 13 | +## Problem |
| 14 | +There are a total of `numCourses` courses you have to take, labeled from `0` to `numCourses - 1`. You are given an array `prerequisites` where `prerequisites[i] = [ai, bi]` indicates that you must take course `bi` first if you want to take course `ai`. |
| 15 | + |
| 16 | +For example, the pair `[0, 1]`, indicates that to take course 0 you have to first take course `1`. |
| 17 | +Return the ordering of courses you should take to finish all courses. If there are many valid answers, return any of them. If it is impossible to finish all courses, return an empty array. |
| 18 | + |
| 19 | + |
| 20 | +### Example 1: |
| 21 | + |
| 22 | +``` |
| 23 | +Input: numCourses = 2, prerequisites = [[1,0]] |
| 24 | +Output: [0,1] |
| 25 | +Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is [0,1]. |
| 26 | +``` |
| 27 | + |
| 28 | +### Example 2: |
| 29 | + |
| 30 | +``` |
| 31 | +Input: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]] |
| 32 | +Output: [0,2,1,3] |
| 33 | +Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. |
| 34 | +So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3]. |
| 35 | +``` |
| 36 | + |
| 37 | +### Example 3: |
| 38 | + |
| 39 | +``` |
| 40 | +Input: numCourses = 1, prerequisites = [] |
| 41 | +Output: [0] |
| 42 | +``` |
| 43 | + |
| 44 | +### Constraints: |
| 45 | +- `1 <= numCourses <= 2000` |
| 46 | +- `0 <= prerequisites.length <= numCourses * (numCourses - 1)` |
| 47 | +- `prerequisites[i].length == 2` |
| 48 | +- `0 <= ai, bi < numCourses` |
| 49 | +- `ai != bi` |
| 50 | +- All the pairs `[ai, bi]` are distinct. |
| 51 | + |
| 52 | +## Solution |
| 53 | +The code aims to solve the problem of determining whether it is possible to finish all the given courses without any cyclic dependencies. It uses the topological sort algorithm, specifically Kahn's algorithm, to solve this problem. |
| 54 | + |
| 55 | +1. **Initialization**: |
| 56 | + - Create an empty adjacency list to represent the directed graph. Each node in the graph represents a course, and the edges represent the prerequisites. |
| 57 | + - Create an array called `indegree` of size `numCourses` and initialize all its elements to 0. The `indegree` array will keep track of the number of incoming edges to each course. |
| 58 | + - Create an empty vector `ans` to store the topological order of the courses. |
| 59 | + |
| 60 | +2. **Building the Graph**: |
| 61 | + - Iterate over the `prerequisites` array, which contains pairs of courses indicating the prerequisites. |
| 62 | + - For each pair `[a, b]`, add an edge in the adjacency list from `b` to `a`. This indicates that course `b` must be completed before course `a`. |
| 63 | + - Increment the indegree of course `a` by 1, as it has one more prerequisite. |
| 64 | + |
| 65 | +3. **Performing Topological Sort using Kahn's Algorithm**: |
| 66 | + - Create an empty queue `q` to store the nodes to visit. |
| 67 | + - Iterate over all the courses (0 to `numCourses-1`) and enqueue the courses with an indegree of 0 into the queue. These courses have no prerequisites and can be started immediately. |
| 68 | + - While the queue is not empty, do the following: |
| 69 | + - Dequeue the front element from the queue and store it in a variable `t`. |
| 70 | + - Add `t` to the `ans` vector to keep track of the topological order. |
| 71 | + - For each neighbor `x` of `t` in the adjacency list: |
| 72 | + - Decrement the indegree of `x` by 1 since we are removing the prerequisite `t`. |
| 73 | + - If the indegree of `x` becomes 0, enqueue `x` into the queue. This means that all the prerequisites of course `x` have been completed. |
| 74 | + |
| 75 | +4. **Checking the Result**: |
| 76 | + - After the topological sort is complete, check if the size of the `ans` vector is equal to the total number of courses (`numCourses`). |
| 77 | + - If they are equal, it means that all the courses can be finished without any cyclic dependencies. Return `true`. |
| 78 | + - If the sizes are different, it implies that there is a cycle in the graph, and it is not possible to complete all the courses. Return `false`. |
| 79 | + |
| 80 | + |
| 81 | +## Code in Different Languages |
| 82 | + |
| 83 | +<Tabs> |
| 84 | +<TabItem value="cpp" label="C++"> |
| 85 | + |
| 86 | +```cpp |
| 87 | +class Solution |
| 88 | +{ |
| 89 | +public: |
| 90 | + vector<int> findOrder(int V, int m, vector<vector<int>> prerequisites) |
| 91 | + { |
| 92 | + vector<int> adj[V]; |
| 93 | + for (auto it : prerequisites) { |
| 94 | + adj[it[1]].push_back(it[0]); |
| 95 | + } |
| 96 | + |
| 97 | + |
| 98 | + |
| 99 | + int indegree[V] = {0}; |
| 100 | + for (int i = 0; i < V; i++) { |
| 101 | + for (auto it : adj[i]) { |
| 102 | + indegree[it]++; |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + queue<int> q; |
| 107 | + for (int i = 0; i < V; i++) { |
| 108 | + if (indegree[i] == 0) { |
| 109 | + q.push(i); |
| 110 | + } |
| 111 | + } |
| 112 | + vector<int> topo; |
| 113 | + while (!q.empty()) { |
| 114 | + int node = q.front(); |
| 115 | + q.pop(); |
| 116 | + topo.push_back(node); |
| 117 | + |
| 118 | + for (auto it : adj[node]) { |
| 119 | + indegree[it]--; |
| 120 | + if (indegree[it] == 0) q.push(it); |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + if (topo.size() == V) return topo; |
| 125 | + return {}; |
| 126 | + } |
| 127 | +}; |
| 128 | +``` |
| 129 | +</TabItem> |
| 130 | +<TabItem value="java" label="Java"> |
| 131 | + |
| 132 | +```java |
| 133 | +class Solution { |
| 134 | + static int[] findOrder(int n, int m, ArrayList<ArrayList<Integer>> prerequisites) { |
| 135 | + // Form a graph |
| 136 | + ArrayList<ArrayList<Integer>> adj = new ArrayList<>(); |
| 137 | + for (int i = 0; i < n; i++) { |
| 138 | + adj.add(new ArrayList<>()); |
| 139 | + } |
| 140 | + |
| 141 | + for (int i = 0; i < m; i++) { |
| 142 | + adj.get(prerequisites.get(i).get(1)).add(prerequisites.get(i).get(0)); |
| 143 | + } |
| 144 | + |
| 145 | + |
| 146 | + |
| 147 | + int indegree[] = new int[n]; |
| 148 | + for (int i = 0; i < n; i++) { |
| 149 | + for (int it : adj.get(i)) { |
| 150 | + indegree[it]++; |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + |
| 155 | + Queue<Integer> q = new LinkedList<Integer>(); |
| 156 | + for (int i = 0; i < n; i++) { |
| 157 | + if (indegree[i] == 0) { |
| 158 | + q.add(i); |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + |
| 163 | + int topo[] = new int[n]; |
| 164 | + int ind = 0; |
| 165 | + // o(v + e) |
| 166 | + while (!q.isEmpty()) { |
| 167 | + int node = q.peek(); |
| 168 | + |
| 169 | + q.remove(); |
| 170 | + topo[ind++] = node; |
| 171 | + // node is in your topo sort |
| 172 | + // so please remove it from the indegree |
| 173 | + |
| 174 | + for (int it : adj.get(node)) { |
| 175 | + indegree[it]--; |
| 176 | + if (indegree[it] == 0) q.add(it); |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + |
| 181 | + if (ind == n) return topo; |
| 182 | + int[] arr = {}; |
| 183 | + return arr; |
| 184 | + } |
| 185 | +} |
| 186 | +``` |
| 187 | +</TabItem> |
| 188 | +</Tabs> |
| 189 | + |
| 190 | +## Complexity Analysis |
| 191 | + |
| 192 | +### Time Complexity: $O(V+E)$ |
| 193 | + |
| 194 | +> **Reason**: where V = no. of nodes and E = no. of edges. This is a simple BFS algorithm. |
| 195 | +
|
| 196 | +### Space Complexity: $O(N) + O(N) ~ O(2N)$ |
| 197 | + |
| 198 | + |
| 199 | +## References |
| 200 | + |
| 201 | +- **LeetCode Problem**: [Course Schedule ii](https://leetcode.com/problems/course-schedule-ii/description/) |
| 202 | + |
| 203 | +- **Leetcode Solutions:** [Course Schedule ii](https://leetcode.com/problems/course-schedule-ii/solutions/) |
0 commit comments