刷这题的时候,又巩固了一下我的拓扑排序
需要先了解一下拓扑排序这个数据结构才能接着往下做
import java.util.*;
/**
* @author xnl
* @Description:
* @date: 2022/7/25 21:57
*/
// 使用深度优先算法
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
int numCourses = 4;
int[][] prerequisites = {{1,0},{2,0},{3,1},{3,2}};
System.out.println(Arrays.toString(solution.findOrder(numCourses, prerequisites)));
}
// 存储有向图
List<List<Integer>> edges;
// 记录每个点的状态 0-未搜索, 1-搜索中,2已完成
int[] visited;
// 用数组模拟栈,下标n-1为 栈低,0为栈顶
int[] result;
// 判断是否有环
boolean valid = true;
// 栈下标
int index;
public int[] findOrder(int numCourses, int[][] prerequisites) {
// 初始化
edges = new ArrayList<>();
for (int i = 0; i < numCourses; i++){
edges.add(new ArrayList<>());
}
visited = new int[numCourses];
result = new int[numCourses];
index = numCourses - 1;
for (int[] prerequisite : prerequisites) {
edges.get(prerequisite[1]).add(prerequisite[0]);
}
// 每次挑选一个未搜索的节点,开始进行深度优先搜索,需要保证没有环
for (int i = 0; i < numCourses && valid; i++){
if (visited[i] == 0){
dfs(i);
}
}
if (!valid){
return new int[0];
}
return result;
}
private void dfs(int u){
// 将节点记为搜索中
visited[u] = 1;
// 搜索相邻节点
// 只要发现有环,立刻停止搜索
for (int v : edges.get(u)){
// 如果未搜索,那么搜索相邻的节点
if (visited[v] == 0){
dfs(v);
if (!valid){
return;
}
} else if (visited[v] == 1){ // 说明有环
valid = false;
return;
}
}
// 将节点标记为已完成
visited[u] =2;
result[index--] = u;
}
}
/**
* 使用广度优先算法
*/
class Solution2 {
List<List<Integer>> edges;
int[] indeg;
int[] result;
int index;
public int[] findOrder(int numCourses, int[][] prerequisites) {
edges = new ArrayList<>();
indeg = new int[numCourses];
result = new int[numCourses];
index = 0;
for (int i = 0; i < numCourses; i++){
edges.add(new ArrayList<>());
}
for (int[] prerequisite : prerequisites) {
edges.get(prerequisite[1]).add(prerequisite[0]);
// 记录一被引用得到次数
++indeg[prerequisite[0]];
}
Queue<Integer> queue = new ArrayDeque<>();
// 记录一下入度为0 的数进队列
for (int i = 0; i < numCourses; i++){
if (indeg[i] == 0){
queue.offer(i);
}
}
while (!queue.isEmpty()){
Integer u = queue.poll();
result[index++] = u;
for (int v : edges.get(u)) {
--indeg[v];
// 如果没有入度,那就代表可以选修这个课程了
if (indeg[v] == 0){
queue.offer(v);
}
}
}
return index == numCourses ? result : new int[0];
}
}