Skip to content

Commit 1d42653

Browse files
authored
Merge pull request #995 from shreyash3087/add/leetcode-207
Docs: Added Solution to Lettcode 207
2 parents ab92d0b + 2e6161b commit 1d42653

File tree

2 files changed

+215
-1
lines changed

2 files changed

+215
-1
lines changed

dsa-problems/leetcode-problems/0200-0299.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export const problems = [
5656
"problemName": "207. Course Schedule",
5757
"difficulty": "Medium",
5858
"leetCodeLink": "https://leetcode.com/problems/course-schedule",
59-
"solutionLink": "#"
59+
"solutionLink": "/dsa-solutions/lc-solutions/0200-0299/course-schedule"
6060
},
6161
{
6262
"problemName": "208. Implement Trie (Prefix Tree)",
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
---
2+
id: course-schedule
3+
title: Course Schedule
4+
sidebar_label: 0207 Course Schedule
5+
tags:
6+
- Depth-First Search
7+
- Topological Sort
8+
- Graph
9+
- Breadth-First Search
10+
- Recursion
11+
description: "This document provides a solution to the Course Schedule problem."
12+
---
13+
14+
## Problem
15+
You are given a total of numCourses courses labeled from 0 to numCourses - 1. You are also given an array prerequisites where $\text{prerequisites[i]} = [ a^i , b^i ]$ indicates that you must take course $b^i$ first if you want to take course $a^i$ .
16+
17+
For example, the pair [0, 1] indicates that to take course 0 you have to first take course 1.
18+
Return `true` if you can finish all courses. Otherwise, return `false`.
19+
20+
### Example 1:
21+
22+
```
23+
Input: numCourses = 2, prerequisites = [[1,0]]
24+
Output: true
25+
Explanation: There are a total of 2 courses to take.
26+
To take course 1 you should have finished course 0. So it is possible.
27+
```
28+
29+
### Example 2:
30+
31+
```
32+
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
33+
Output: false
34+
Explanation: There are a total of 2 courses to take.
35+
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.
36+
```
37+
38+
### Constraints:
39+
- `1 <= numCourses <= 2000`
40+
- `0 <= prerequisites.length <= 5000`
41+
- `prerequisites[i].length == 2`
42+
- `0 <= ai, bi < numCourses `
43+
- All the pairs prerequisites[i] are **unique**.
44+
## Solution
45+
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.
46+
47+
1. **Initialization**:
48+
- Create an empty adjacency list to represent the directed graph. Each node in the graph represents a course, and the edges represent the prerequisites.
49+
- 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.
50+
- Create an empty vector `ans` to store the topological order of the courses.
51+
52+
2. **Building the Graph**:
53+
- Iterate over the `prerequisites` array, which contains pairs of courses indicating the prerequisites.
54+
- 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`.
55+
- Increment the indegree of course `a` by 1, as it has one more prerequisite.
56+
57+
3. **Performing Topological Sort using Kahn's Algorithm**:
58+
- Create an empty queue `q` to store the nodes to visit.
59+
- 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.
60+
- While the queue is not empty, do the following:
61+
- Dequeue the front element from the queue and store it in a variable `t`.
62+
- Add `t` to the `ans` vector to keep track of the topological order.
63+
- For each neighbor `x` of `t` in the adjacency list:
64+
- Decrement the indegree of `x` by 1 since we are removing the prerequisite `t`.
65+
- If the indegree of `x` becomes 0, enqueue `x` into the queue. This means that all the prerequisites of course `x` have been completed.
66+
67+
4. **Checking the Result**:
68+
- After the topological sort is complete, check if the size of the `ans` vector is equal to the total number of courses (`numCourses`).
69+
- If they are equal, it means that all the courses can be finished without any cyclic dependencies. Return `true`.
70+
- 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`.
71+
72+
73+
## Code in Different Languages
74+
75+
<Tabs>
76+
<TabItem value="cpp" label="C++">
77+
<SolutionAuthor name="@Shreyash3087"/>
78+
79+
```cpp
80+
class Solution {
81+
public:
82+
bool canFinish(int n, vector<vector<int>>& prerequisites) {
83+
vector<int> adj[n];
84+
vector<int> indegree(n, 0);
85+
vector<int> ans;
86+
87+
for(auto x: prerequisites){
88+
adj[x[0]].push_back(x[1]);
89+
indegree[x[1]]++;
90+
}
91+
92+
queue<int> q;
93+
for(int i = 0; i < n; i++){
94+
if(indegree[i] == 0){
95+
q.push(i);
96+
}
97+
}
98+
99+
while(!q.empty()){
100+
auto t = q.front();
101+
ans.push_back(t);
102+
q.pop();
103+
104+
for(auto x: adj[t]){
105+
indegree[x]--;
106+
if(indegree[x] == 0){
107+
q.push(x);
108+
}
109+
}
110+
}
111+
return ans.size() == n;
112+
}
113+
};
114+
```
115+
</TabItem>
116+
<TabItem value="java" label="Java">
117+
<SolutionAuthor name="@Shreyash3087"/>
118+
119+
```java
120+
class Solution {
121+
public boolean canFinish(int n, int[][] prerequisites) {
122+
List<Integer>[] adj = new List[n];
123+
int[] indegree = new int[n];
124+
List<Integer> ans = new ArrayList<>();
125+
126+
for (int[] pair : prerequisites) {
127+
int course = pair[0];
128+
int prerequisite = pair[1];
129+
if (adj[prerequisite] == null) {
130+
adj[prerequisite] = new ArrayList<>();
131+
}
132+
adj[prerequisite].add(course);
133+
indegree[course]++;
134+
}
135+
136+
Queue<Integer> queue = new LinkedList<>();
137+
for (int i = 0; i < n; i++) {
138+
if (indegree[i] == 0) {
139+
queue.offer(i);
140+
}
141+
}
142+
143+
while (!queue.isEmpty()) {
144+
int current = queue.poll();
145+
ans.add(current);
146+
147+
if (adj[current] != null) {
148+
for (int next : adj[current]) {
149+
indegree[next]--;
150+
if (indegree[next] == 0) {
151+
queue.offer(next);
152+
}
153+
}
154+
}
155+
}
156+
157+
return ans.size() == n;
158+
}
159+
}
160+
```
161+
162+
</TabItem>
163+
<TabItem value="python" label="Python">
164+
<SolutionAuthor name="@Shreyash3087"/>
165+
166+
```python
167+
class Solution:
168+
def canFinish(self, n: int, prerequisites: List[List[int]]) -> bool:
169+
adj = [[] for _ in range(n)]
170+
indegree = [0] * n
171+
ans = []
172+
173+
for pair in prerequisites:
174+
course = pair[0]
175+
prerequisite = pair[1]
176+
adj[prerequisite].append(course)
177+
indegree[course] += 1
178+
179+
queue = deque()
180+
for i in range(n):
181+
if indegree[i] == 0:
182+
queue.append(i)
183+
184+
while queue:
185+
current = queue.popleft()
186+
ans.append(current)
187+
188+
for next_course in adj[current]:
189+
indegree[next_course] -= 1
190+
if indegree[next_course] == 0:
191+
queue.append(next_course)
192+
193+
return len(ans) == n
194+
```
195+
</TabItem>
196+
</Tabs>
197+
198+
## Complexity Analysis
199+
200+
### Time Complexity: $O(N + P)$
201+
202+
> **Reason**: Where N is the number of courses and P is the number of prerequisites.
203+
204+
### Space Complexity: $O(N + P)$
205+
206+
:::note
207+
**Reason**: We use an adjacency list to store the graph and an array to store the in-degree of each node.
208+
:::
209+
210+
## References
211+
212+
- **LeetCode Problem**: [Course Schedule](https://leetcode.com/problems/course-schedule/description/)
213+
214+
- **Leetcode Solutions:** [Course Schedule](https://leetcode.com/problems/course-schedule/solutions/)

0 commit comments

Comments
 (0)