Skip to content

Commit 468ba8a

Browse files
Problem 207 (#32)
* add solution and resources * update readme
1 parent 9b555d6 commit 468ba8a

File tree

2 files changed

+130
-1
lines changed

2 files changed

+130
-1
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ As I work through this list I figure I would make a GitHub repo with my solution
4242
31. [Binary Tree Level Order Traversal #102](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/binary-tree-level-102.md)
4343
32. [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
4444
33. [Evaluate Reverse Polish Notation #150](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/polish-notation-150.md)
45-
34. Course Schedule #207
45+
34. [Course Schedule #207](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/course-schedule-207.md)
4646
35. **Implement Trie (Prefix Tree) #208**
4747
36. Coin Change #322
4848
37. Product of Array Except Self #238
@@ -165,6 +165,7 @@ In order to practice with similar data structures I'll be placing each problem i
165165

166166
- [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
167167
- [Number of Provinces #547](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/number-of-provinces-547.md)
168+
- [Course Schedule #207](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/course-schedule-207.md)
168169

169170
### Heap
170171

@@ -203,6 +204,7 @@ Within the problems above there are several patterns that often occur. I plan to
203204
- [Binary Tree Level Order Traversal #102](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/binary-tree-level-102.md)
204205
- [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
205206
- [Number of Provinces #547](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/number-of-provinces-547.md)
207+
- [Course Schedule #207](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/course-schedule-207.md)
206208

207209
### Depth First Search
208210

@@ -214,6 +216,7 @@ Within the problems above there are several patterns that often occur. I plan to
214216
- [Maximum Depth of Binary Tree #104](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/depth-binary-tree-104.md)
215217
- [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
216218
- [Number of Provinces #547](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/number-of-provinces-547.md)
219+
- [Course Schedule #207](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/course-schedule-207.md)
217220

218221
### Divide & Conquer
219222

medium/course-schedule-207.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Course Schedule
2+
3+
Page on leetcode: https://leetcode.com/problems/course-schedule/
4+
5+
## Problem Statement
6+
7+
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.
8+
9+
- For example, the pair [0, 1], indicates that to take course 0 you have to first take course 1.
10+
11+
Return true if you can finish all courses. Otherwise, return false.
12+
13+
### Constraints
14+
15+
- 1 <= numCourses <= 2000
16+
- 0 <= prerequisites.length <= 5000
17+
- prerequisites[i].length == 2
18+
- 0 <= ai, bi < numCourses
19+
- All the pairs prerequisites[i] are unique.
20+
21+
### Example
22+
23+
```
24+
Input: numCourses = 2, prerequisites = [[1,0]]
25+
Output: true
26+
Explanation: There are a total of 2 courses to take.
27+
To take course 1 you should have finished course 0. So it is possible.
28+
```
29+
30+
```
31+
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
32+
Output: false
33+
Explanation: There are a total of 2 courses to take.
34+
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.
35+
```
36+
37+
## Solution
38+
39+
- If courses form a loop it's not possible
40+
- What if there are no prereq's? Does that automatically mean true?
41+
- Could we store in hashmap and see if we find a loop?
42+
- Can a course have multiple pre-reqs?
43+
44+
### Pseudocode
45+
46+
1. Create a map
47+
2. Iterate thru array
48+
3. If prereq isn't in map, and course isn't in map, add to map
49+
4. If prereq is in map and prereq value is current course return false
50+
5. If you go thru whole array then return true
51+
52+
### Initial Attempt
53+
54+
```javascript
55+
const canFinish = function (numCourses, prerequisites) {
56+
const map = new Map();
57+
58+
for (let course of prerequisites) {
59+
const [currCourse, prereq] = course;
60+
// Courses create a loop
61+
if (map.has(prereq) && map.get(prereq) === currCourse) {
62+
return false;
63+
} else if (currCourse === prereq) {
64+
return false;
65+
}
66+
67+
map.set(currCourse, prereq);
68+
}
69+
70+
return true;
71+
};
72+
```
73+
74+
### Optimized Solution
75+
76+
The time complexity of this approach is O(n + p) and space complexity of O(n). You can see an explanation of the solution here: https://www.youtube.com/watch?v=EgI5nU9etnU
77+
78+
There is a good video that explains Topological Sort here: https://www.youtube.com/watch?v=eL-KzMXSXXI
79+
80+
```javascript
81+
const canFinish = function (numCourses, prerequisites) {
82+
// Create an adjacency list with empty arrays
83+
const map = {};
84+
for (let i = 0; i < numCourses; i++) {
85+
map[i] = [];
86+
}
87+
// Add prereqs to adjacency list
88+
for (let j = 0; j < prerequisites.length; j++) {
89+
const [course, prereq] = prerequisites[j];
90+
map[course].push(prereq);
91+
}
92+
93+
// Set for checking if we've seen a node on a DFS path. If so we are in a loop.
94+
const visited = new Set();
95+
96+
// Recursive helper function
97+
function dfs(course) {
98+
if (visited.has(course)) {
99+
return false;
100+
}
101+
if (map[course] === []) {
102+
return true;
103+
}
104+
visited.add(course);
105+
// Check all prereqs of this course
106+
for (prereq of map[course]) {
107+
if (!dfs(prereq)) {
108+
return false;
109+
}
110+
}
111+
// remove course from visited and set prereqs to empty if they were all true. Helps speed up algorithm to not do double checking.
112+
visited.delete(course);
113+
map[course] = [];
114+
return true;
115+
}
116+
117+
// Check all courses in case the graph is not connected.
118+
for (let k = 0; k < numCourses; k++) {
119+
if (!dfs(k)) {
120+
return false;
121+
}
122+
}
123+
124+
return true;
125+
};
126+
```

0 commit comments

Comments
 (0)