明确入度和出度
邻接表用来存储出度
数组存储入度
有环则代表无法完成
最后遍历出度来确定是否有环,使用bfs来遍历
附上代码
课程表1
class Solution {
public boolean canFinish(int n, int[][] p) {
//存储入度,数组下标代表课程
int[] in = new int[n];
//构建邻接表存储拓扑排序
Map<Integer,List<Integer>> map = new HashMap<>();
for(int i = 0;i < p.length;i++){
int a = p[i][0];//后一个
int b = p[i][1];//前一个
if(!map.containsKey(b)){
map.put(b,new LinkedList<>());
}
map.get(b).add(a);
in[a]++;//增加入度
}
Queue<Integer> q = new LinkedList<>();
for(int i = 0;i < n;i++){
if(in[i] == 0){
q.add(i);
}
}
while(!q.isEmpty()){
for(int a : map.getOrDefault(q.poll(),new LinkedList<>())){
in[a]--;
if(in[a] == 0){
q.add(a);
}
}
}
for(int i = 0;i < n;i++){
if(in[i] != 0){
return false;
}
}
return true;
}
}
课程表2
class Solution {
public int[] findOrder(int n, int[][] p) {
//输出数组
int[] out = new int[n];
int cur = 0;//指针
//入度
int[] in = new int[n];
//构建邻接表
Map<Integer,List<Integer>> edges = new HashMap<>();
for(int i = 0;i < p.length;i++){
int a = p[i][0];//1
int b = p[i][1];//0 -> 1
if(!edges.containsKey(b)){
edges.put(b,new LinkedList<>());
}
edges.get(b).add(a);
in[a]++;
}
//bfs
Queue<Integer> q = new LinkedList<>();
for(int i = 0;i < n;i++){
if(in[i] == 0){
out[cur++] = i;
q.add(i);
}
}
while(!q.isEmpty()){
for(int a : edges.getOrDefault(q.poll(),new LinkedList<>())){
in[a]--;
if(in[a] == 0){
out[cur++] = a;
q.add(a);
}
}
}
for(int i = 0;i < n;i++){
if(in[i] != 0){
return new int[0];
}
}
return out;
}
}