Course Schedule: Day 29 of the May LeetCoding Challenge
“Data dominates. If you’ve chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.”
~ Rob Pike
Day 29 of the May LeetCoding Challenge by Leetcode
Problem definition: Course Schedule
There are a total of numCourses
courses you have to take, labeled from 0
to numCourses-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?
Sample Testcase
Testcase 1
Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Testcase 2
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: 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.
Constraints:
- The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
- You may assume that there are no duplicate edges in the input prerequisites.
1 <= numCourses <= 10^5
I highly encourage you to attempt this problem on your own before looking at my solution.
💡 Hints:
- 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.
- Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
- Topological sort could also be done via BFS.
Approach
Consider each course as a node and make an edge from the prerequisite course to the current course. Next, count the in-degree and out-degree of each node.
(Note: For a directed graph and a vertex , the Out-Degree of refers to the number of arcs incident from . That is, the number of arcs directed away from the vertex . The In-Degree of refers to the number of arcs incident to . That is, the number of arcs directed towards the vertex. Read more about it here.)
Next, append all nodes with in-degree equal to 0 in a stack. When a node is popped from the child reduce the child’s in-degree by one and increment the counter for every node popped.
If counter is equal to the no. of courses a cycle does not exist. Return true
.
Solution
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
inDegree={}
for i in range(numCourses):
inDegree[i]=0
outDegree = collections.defaultdict(list)
for a, b in prerequisites:
inDegree[b] += 1
outDegree[a].append(b)
count = 0
visited = []
for i in range(numCourses):
if inDegree[i] == 0:
visited.append(i)
while(visited):
curr = visited.pop()
count += 1
for child in outDegree[curr]:
inDegree[child] -= 1
if inDegree[child] == 0:
visited.append(child)
return count == numCourses
Submission Details
Total test cases passed: 46 / 46
Runtime: 76 ms
Memory Usage: 14.2 MB
Note: This submission was better than 94.50% of Python3 solutions in terms of runtime! Try to come up with a better approach! 🌚
I would really recommend you to explore this side of the Computer Science and tune in to the journey of competitive programming to write better, cleaner, efficient and optimal code! 😀
If you have a better approach to this problem, or for any other queries feel free to reach out to me! 😇