Solution 1
也就是 0207. Course Schedule 的具体版,也就是要输出具体的拓扑排序结果。
基于现在的有向边定义,最小序节点就是最优先的课程。
- 时间复杂度: O ( N + M ) O(N + M) O(N+M),其中 N N N图的节点数量,即输入的课程数; M M M为边的数量,即输入的前提条件数量;拓扑排序中DFS完成所有节点的一次线性遍历,整体时间复杂度
- 空间复杂度: O ( N + M ) O(N+M) O(N+M),其中 N N N图的节点数量,即输入的课程数; M M M为边的数量,即输入的前提条件数量;搜索过程中对节点状态和图的整体存储占用
class Solution {
private:
vector<vector<int>> edges; // 输入图
vector<int> isVisited; // 搜索验证,0:未搜索,1:可达节点未全部遍历,2:可达节点全部遍历
vector<int> ans; // 拓扑排序结果
bool hasCycle = false; // 是否有环
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
this->edges = vector<vector<int>>(numCourses, vector<int>());
this->isVisited = vector<int>(numCourses);
for (auto item: prerequisites) {
this->edges[item[0]].push_back(item[1]);
}
this->topologicalSort(numCourses);
if (this->hasCycle) {
return vector<int>();
} else {
return this->ans;
}
}
private:
void topologicalSort(int num) {
for (int vertex = 0; vertex < num; vertex++) {
if (isVisited[vertex] == 0) {
this->dfs(vertex);
}
if (this->hasCycle) {
return; // 发现环,提前终止
}
}
}
void dfs(int vertex) {
this->isVisited[vertex] = 1;
for (auto target: edges[vertex]) {
if (isVisited[target] == 0) {
this->dfs(target);
if (this->hasCycle) {
return; // 发现环,提前终止
}
} else if (this->isVisited[target] == 1) {
this->hasCycle = true;
return; // 发现环,提前终止
}
}
isVisited[vertex] = 2; // 完成全部可达节点遍历
ans.push_back(vertex);
}
};
Solution 2
Solution 1的Python实现
class Solution:
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
edges = collections.defaultdict(list)
is_visited = [0] * numCourses
ans = list()
has_cycle = False
def dfs(vertex: int) -> None:
nonlocal edges, is_visited, has_cycle
is_visited[vertex] = 1
for target in edges[vertex]:
if is_visited[target] == 0:
dfs(target)
if has_cycle: return
elif is_visited[target] == 1:
has_cycle = True
return
is_visited[vertex] = 2
ans.append(vertex)
def topological_sort(num_vertex: int) -> None:
nonlocal is_visited, has_cycle
for vertex in range(num_vertex):
if is_visited[vertex] == 0:
dfs(vertex)
if has_cycle: return
# ====================================
for item in prerequisites:
edges[item[0]].append(item[1])
topological_sort(numCourses)
if has_cycle:
return []
else:
return ans