拓扑排序经典问题 - 课程表:
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.
Example 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.
Example 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.
两种解法:
- 先建立adjancency list,然后判断是否有环
这个方法比较straightforward,通过递归判断是否有环
class Solution {
public boolean findCircle(int i, List<List<Integer>> courseList, int[] visited) {
if(visited[i] == 1) return true;
if(visited[i] == 2) return false;
// 总结起来,if(visited[i] == 2) return false; 这一行代码的目的是在深度优先搜索过程中,如果遇到已经完全探索过的节点,立即返回 false
visited[i] = 1;
for(int next: courseList.get(i)) {
if(findCircle(next, courseList, visited)) {
return true;
}
}
visited[i] = 2;
return false;
}
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> courseList = new ArrayList<>(numCourses);
for(int i = 0; i < numCourses; i++) {
courseList.add(new ArrayList<>());
}
for(int[] pre: prerequisites) {
courseList.get(pre[1]).add(pre[0]);
}
int[] visited = new int[numCourses];
for(int i = 0; i < numCourses; i++) {
if(findCircle(i, courseList, visited)) {
return false;
}
}
return true;
}
}
- 通过拓扑排序,限时找到所有课程的入度,这需要一个array来辅助,然后建立一个queue,先从无入度的顶点开始遍历,然后将所有以该门课为入度的起点的课的入度减一,最后有一个count判断所有入度的节点,如果等于numCourses则说明结果正常,否则返回空数组
class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
Map<Integer, List<Integer>> map = new HashMap<>();
int[] indegree = new int[numCourses]; // indegree指的是当前的课有多少prerequisite
for(int i = 0; i < numCourses; i++) {
map.put(i, new ArrayList<>());
}
for(int[] pre: prerequisites) {
map.get(pre[1]).add(pre[0]);
indegree[pre[0]]++;
}
Deque<Integer> queue = new ArrayDeque<>();
for(int i = 0; i < numCourses; i++) {
if(indegree[i] == 0) {
queue.offer(i);
}
}
int[] res = new int[numCourses];
int index = 0;
while(!queue.isEmpty()) {
int curr = queue.poll();
if (index < numCourses) {
res[index] = curr;
}
index++;
for(int next: map.get(curr)) {
indegree[next]--;
if(indegree[next] == 0) {
queue.offer(next);
}
}
}
return index == numCourses ? res : new int[0];
}
}
210题和207题差不多,不做考虑