LeetCode link: 207. Course Schedule
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.
- For example, the pair
[0, 1], indicates that to take course0you have to first take course1.
Return true if you can finish all courses. Otherwise, return false.
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.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.1 <= numCourses <= 20000 <= prerequisites.length <= 5000prerequisites[i].length == 20 <= ai, bi < numCourses- All the pairs
prerequisites[i]are unique.
- Each course can be abstracted as a vertex in a graph.
- The existence of a dependency relationship indicates that it is a directed graph.
- Course A depends on course B, which can be abstracted as course A needs course B to unlock, and the in-degree of course A needs to be increased by 1.
- So an
in_degreesarray is needed to save the in-degree of each course. - Courses with an in-degree of 0 can be studied first, so they can be put into a queue and processed one by one.
- Courses with an in-degree of 0 unlock other courses. This is the direction of the directed graph. Don't get it wrong.
- After each course is completed, the in-degree of other courses that depend on it is reduced by 1. If it is found that the in-degree of the course is 0 after deducting 1, the course is added to the queue.
- Which courses can be unlocked by a course need to be saved with a map or an array
courses_list. - If the in-degree of all courses is 0 at the end, return
true, otherwise it means that there is a cycle in the directed graph, and returnfalse. - The above algorithm is a breadth-first algorithm.
- Can you use a depth-first algorithm to solve it?
- Simply replacing the queue used in the breadth-first algorithm with a stack will create a depth-first algorithm.
V is vertices.length.
E is edges.length.
- Time:
O(V + E). - Space:
O(V + E).
from collections import deque
class Solution:
def canFinish(self, num_courses: int, prerequisites: List[List[int]]) -> bool:
courses_list = [set() for _ in range(num_courses)] # index: course, value: courses depend on course
in_degrees = [0] * num_courses
for course_item, course in prerequisites:
courses_list[course].add(course_item)
in_degrees[course_item] += 1
ok_course_queue = deque(
[i for i, in_degree in enumerate(in_degrees) if in_degree == 0]
)
while ok_course_queue:
ok_course = ok_course_queue.popleft()
for course in courses_list[ok_course]:
in_degrees[course] -= 1
if in_degrees[course] == 0:
ok_course_queue.append(course)
return sum(in_degrees) == 0class Solution:
def canFinish(self, num_courses: int, prerequisites: List[List[int]]) -> bool:
courses_list = [set() for _ in range(num_courses)] # index: course, value: courses depend on course
in_degrees = [0] * num_courses
for prerequisite in prerequisites:
courses_list[prerequisite[1]].add(prerequisite[0])
in_degrees[prerequisite[0]] += 1
ok_courses = [i for i, in_degree in enumerate(in_degrees) if in_degree == 0]
while ok_courses:
ok_course = ok_courses.pop()
for course in courses_list[ok_course]:
in_degrees[course] -= 1
if in_degrees[course] == 0:
ok_courses.append(course)
return sum(in_degrees) == 0class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
var inDegrees = new int[numCourses];
var coursesList = new ArrayList<HashSet<Integer>>(); // index: course, value: courses depend on course
for (var i = 0; i < numCourses; i++) {
coursesList.add(new HashSet<Integer>());
}
for (var prerequisite : prerequisites) {
inDegrees[prerequisite[0]]++;
var courses = coursesList.get(prerequisite[1]);
courses.add(prerequisite[0]);
}
var okCourses = new ArrayDeque<Integer>();
var studiedCourseCount = 0;
for (var course = 0; course < inDegrees.length; course++) {
if (inDegrees[course] == 0) {
okCourses.add(course);
}
}
while (!okCourses.isEmpty()) {
var okCourse = okCourses.poll();
studiedCourseCount++;
for (var course : coursesList.get(okCourse)) {
inDegrees[course]--;
if (inDegrees[course] == 0) {
okCourses.add(course);
}
}
}
return studiedCourseCount == numCourses;
}
}class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
var inDegrees = new int[numCourses];
var coursesList = new ArrayList<HashSet<Integer>>(); // index: course, value: courses depend on course
for (var i = 0; i < numCourses; i++) {
coursesList.add(new HashSet<Integer>());
}
for (var prerequisite : prerequisites) {
inDegrees[prerequisite[0]]++;
var courses = coursesList.get(prerequisite[1]);
courses.add(prerequisite[0]);
}
var okCourses = new Stack<Integer>();
var studiedCourseCount = 0;
for (var course = 0; course < inDegrees.length; course++) {
if (inDegrees[course] == 0) {
okCourses.push(course);
}
}
while (!okCourses.isEmpty()) {
var okCourse = okCourses.pop();
studiedCourseCount++;
for (var course : coursesList.get(okCourse)) {
inDegrees[course]--;
if (inDegrees[course] == 0) {
okCourses.push(course);
}
}
}
return studiedCourseCount == numCourses;
}
}class Solution {
public:
bool canFinish(int num_courses, vector<vector<int>>& prerequisites) {
auto in_degrees = vector<int>(num_courses);
auto courses_vector = vector<set<int>>(num_courses); // index: course, value: courses depend on course
for (auto& prerequisite : prerequisites) {
in_degrees[prerequisite[0]]++;
courses_vector[prerequisite[1]].insert(prerequisite[0]);
}
queue<int> ok_courses;
auto studied_course_count = 0;
for (auto course = 0; course < in_degrees.size(); course++) {
if (in_degrees[course] == 0) {
ok_courses.push(course);
}
}
while (!ok_courses.empty()) {
auto okCourse = ok_courses.front();
ok_courses.pop();
studied_course_count++;
for (auto course : courses_vector[okCourse]) {
in_degrees[course]--;
if (in_degrees[course] == 0) {
ok_courses.push(course);
}
}
}
return studied_course_count == num_courses;
}
};class Solution {
public:
bool canFinish(int num_courses, vector<vector<int>>& prerequisites) {
auto in_degrees = vector<int>(num_courses);
auto courses_vector = vector<set<int>>(num_courses); // index: course, value: courses depend on course
for (auto& prerequisite : prerequisites) {
in_degrees[prerequisite[0]]++;
courses_vector[prerequisite[1]].insert(prerequisite[0]);
}
stack<int> ok_courses;
auto studied_course_count = 0;
for (auto course = 0; course < in_degrees.size(); course++) {
if (in_degrees[course] == 0) {
ok_courses.push(course);
}
}
while (!ok_courses.empty()) {
auto okCourse = ok_courses.top();
ok_courses.pop();
studied_course_count++;
for (auto course : courses_vector[okCourse]) {
in_degrees[course]--;
if (in_degrees[course] == 0) {
ok_courses.push(course);
}
}
}
return studied_course_count == num_courses;
}
};// Welcome to create a PR to complete the code of this language, thanks!public class Solution {
public bool CanFinish(int numCourses, int[][] prerequisites)
{
var inDegrees = new int[numCourses];
var coursesList = new List<HashSet<int>>(); // index: course, value: courses depend on course
for (int i = 0; i < numCourses; i++)
coursesList.Add(new HashSet<int>());
foreach (int[] prerequisite in prerequisites)
{
inDegrees[prerequisite[0]]++;
var courses = coursesList[prerequisite[1]];
courses.Add(prerequisite[0]);
}
var okCourses = new Queue<int>();
int studiedCourseCount = 0;
for (int course = 0; course < inDegrees.Length; course++)
{
if (inDegrees[course] == 0)
{
okCourses.Enqueue(course);
}
}
while (okCourses.Count > 0)
{
int okCourse = okCourses.Dequeue();
studiedCourseCount++;
foreach (int course in coursesList[okCourse])
{
inDegrees[course]--;
if (inDegrees[course] == 0)
{
okCourses.Enqueue(course);
}
}
}
return studiedCourseCount == numCourses;
}
}public class Solution {
public bool CanFinish(int numCourses, int[][] prerequisites)
{
var inDegrees = new int[numCourses];
var coursesList = new List<HashSet<int>>(); // index: course, value: courses depend on course
for (int i = 0; i < numCourses; i++)
coursesList.Add(new HashSet<int>());
foreach (int[] prerequisite in prerequisites)
{
inDegrees[prerequisite[0]]++;
var courses = coursesList[prerequisite[1]];
courses.Add(prerequisite[0]);
}
var okCourses = new Stack<int>();
int studiedCourseCount = 0;
for (int course = 0; course < inDegrees.Length; course++)
{
if (inDegrees[course] == 0)
{
okCourses.Push(course);
}
}
while (okCourses.Count > 0)
{
int okCourse = okCourses.Pop();
studiedCourseCount++;
foreach (int course in coursesList[okCourse])
{
inDegrees[course]--;
if (inDegrees[course] == 0)
{
okCourses.Push(course);
}
}
}
return studiedCourseCount == numCourses;
}
}// Welcome to create a PR to complete the code of this language, thanks!# Welcome to create a PR to complete the code of this language, thanks!// Welcome to create a PR to complete the code of this language, thanks!// Welcome to create a PR to complete the code of this language, thanks!// Welcome to create a PR to complete the code of this language, thanks!// Welcome to create a PR to complete the code of this language, thanks!// Welcome to create a PR to complete the code of this language, thanks!