[LeetCode] Course Schedule

简介: As suggested by the hints, this problem is equivalent to detecting a cycle in the graph represented by prerequisites.

As suggested by the hints, this problem is equivalent to detecting a cycle in the graph represented by prerequisites. Both BFS and DFS can be used to solve it using the idea oftopological sort. If you find yourself unfamiliar with these concepts, you may refer to their wikipedia pages. Specifically, you may only need to refer to the link in the third hint to solve this problem.

Since pair<int, int> is inconvenient for the implementation of graph algorithms, we first transform it to a graph. If course u is a prerequisite of course v, we will add a directed edge from node u to node v.


BFS

BFS uses the indegrees of each node. We will first try to find a node with 0 indegree. If we fail to do so, there must be a cycle in the graph and we return false. Otherwise we have found one. We set its indegree to be -1 to prevent from visiting it again and reduce the indegrees of all its neighbors by 1. This process will be repeated for n (number of nodes) times. If we have not returned false, we will return true.

 1 class Solution {
 2 public:
 3     bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
 4         vector<unordered_set<int>> graph = make_graph(numCourses, prerequisites);
 5         vector<int> degrees = compute_indegree(graph);
 6         for (int i = 0; i < numCourses; i++) {
 7             int j = 0;
 8             for (; j < numCourses; j++)
 9                 if (!degrees[j]) break;
10             if (j == numCourses) return false;
11             degrees[j] = -1;
12             for (int neigh : graph[j])
13                 degrees[neigh]--;
14         }
15         return true;
16     }
17 private:
18     vector<unordered_set<int>> make_graph(int numCourses, vector<pair<int, int>>& prerequisites) {
19         vector<unordered_set<int>> graph(numCourses);
20         for (auto pre : prerequisites)
21             graph[pre.second].insert(pre.first);
22         return graph;
23     }
24     vector<int> compute_indegree(vector<unordered_set<int>>& graph) {
25         vector<int> degrees(graph.size(), 0);
26         for (auto neighbors : graph)
27             for (int neigh : neighbors)
28                 degrees[neigh]++;
29         return degrees;
30     }
31 };

DFS

For DFS, it will first visit a node, then one neighbor of it, then one neighbor of this neighbor... and so on. If it meets a node which was visited in the current process of DFS visit, a cycle is detected and we will return false. Otherwise it will start from another unvisited node and repeat this process till all the nodes have been visited. Note that you should make two records: one is to record all the visited nodes and the other is to record the visited nodes in the current DFS visit.

The code is as follows. We use a vector<bool> visited to record all the visited nodes and another vector<bool> onpath to record the visited nodes of the current DFS visit. Once the current visit is finished, we reset the onpath value of the starting node to false.

 1 class Solution {
 2 public:
 3     bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
 4         vector<unordered_set<int>> graph = make_graph(numCourses, prerequisites);
 5         vector<bool> onpath(numCourses, false), visited(numCourses, false);
 6         for (int i = 0; i < numCourses; i++)
 7             if (!visited[i] && dfs_cycle(graph, i, onpath, visited))
 8                 return false;
 9         return true;
10     }
11 private:
12     vector<unordered_set<int>> make_graph(int numCourses, vector<pair<int, int>>& prerequisites) {
13         vector<unordered_set<int>> graph(numCourses);
14         for (auto pre : prerequisites)
15             graph[pre.second].insert(pre.first);
16         return graph;
17     } 
18     bool dfs_cycle(vector<unordered_set<int>>& graph, int node, vector<bool>& onpath, vector<bool>& visited) {
19         if (visited[node]) return false;
20         onpath[node] = visited[node] = true; 
21         for (int neigh : graph[node])
22             if (onpath[neigh] || dfs_cycle(graph, neigh, onpath, visited))
23                 return true;
24         return onpath[node] = false;
25     }
26 }; 

 

目录
相关文章
|
索引
LeetCode 207. Course Schedule
现在你总共有 n 门课需要选,记为 0 到 n-1。 在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?
78 0
LeetCode 207. Course Schedule
[LeetCode] Course Schedule III 课程清单之三
There are n different online courses numbered from 1 to n. Each course has some duration(course length) tand closed on dth day.
1086 0
LeetCode - 207. Course Schedule
207. Course Schedule  Problem's Link  ---------------------------------------------------------------------------- Mean:  给定一个有向图,判断是否存在top_sort序列.
987 0
[LeetCode] Course Schedule II
Well, this problem is spiritually similar to to Course Schedule. You only need to store the nodes in the order you visit into a vector during BFS or DFS.
693 0
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
41 6
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
35 4
|
1月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
73 2
|
1月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
35 7