207. Course Schedule
207,课程表。题目链接
判断给定的图形是不是有环图,有两种解决办法是:深度优先搜索,和广度优先搜索
1.深度优先搜索
思路:使用一个onStack[]来判定当前访问到的节点是不是在当前的路径上,如果是,则证明有环
/**
* 深度优先搜索判断环
*/
class Topological {
private final int N;
private List<Integer>[] bags;
private boolean[] marked;
private boolean hasCycle = false;
private boolean[] onStack;
public Topological(int N, int[][] prerequisites) {
this.N = N;
bags = (List<Integer>[]) new List[N];
marked = new boolean[N];
onStack = new boolean[N];
for (int i = 0; i < N; i++) {
bags[i] = new ArrayList<>();
}
for (int[] pre : prerequisites) {
bags[pre[0]].add(pre[1]);
}
for (int v = 0; v < N; v++) {
if (!marked[v])
dfs(v);
}
}
private void dfs(int v) {
onStack[v] = true;
marked[v] = true;
for (int w : bags[v]) {
if (hasCycle) return;
if (!marked[w])
dfs(w);
else if (onStack[v] == onStack[w]) hasCycle = true;
}
onStack[v] = false;
}
public boolean isHasCycle() {
return hasCycle;
}
}
2.广度优先搜索:
有没有想起来教材数据结构,判定拓扑的方法.首先删掉入度为0的节点,然后删掉这个节点的链接.在判断其他节点是否入度为0.最后如果能够全部删除节点,证明无环
/**
* 广度优先搜索判断环
*/
class Topological1 {
private int N;
private int[] inDegree; //入度表
private List<Integer>[] adj;
public Topological1(int n, int[][] prerequisites) {
N = n;
inDegree = new int[N];
adj = (List<Integer>[]) new List[n];
for (int i = 0; i < N; i++) {
adj[i] = new ArrayList<>();
}
for (int[] pre : prerequisites) {
inDegree[pre[1]]++;
adj[pre[0]].add(pre[1]);
}
bfs();
}
private void bfs() {
Queue<Integer> queue = new ArrayDeque<>();
for (int i = 0; i < N; i++) {
if (inDegree[i] == 0) queue.add(i);
}
while (!queue.isEmpty()) {
int v = queue.poll();
N--;
for (int w : adj[v]) {
//删除节点的时候减去其他节点的入度
if (--inDegree[w] == 0) queue.add(w);
}
}
}
public boolean hasCycle() {
return N == 0;
}
}