题目: 207. 课程表
思路:
-
深搜:判断是否有环。每个节点有三种状态,未访问0,正在访问1,已经访问2.深搜过程中,第一次遇到该节点,把状态置为1;若本次深搜再次遇到状态为1的,说明有环,结束;若某个节点往下已经搜索完了都没有环,就把状态置为2,表示已经访问结束.
-
广搜:需要给每个节点建立一个入度表,表示有多少个节点指向本节点.建立一个队列,首先把入度为0的节点入队列,然后若队列不为空,则弹出队头元素,更新入度表,把队头元素指向的节点的入度减一,此时如果有节点入度变为1,就加入队列.根据这个算法,如果没有环,所有的节点都会入出队列一次,所以统计一下出入队列的节点数即可判断是否有环.
代码:dfs
class Solution {
int[] visited;
boolean res = true;
public boolean canFinish(int numCourses, int[][] prerequisites) {
Set<Integer> sum = new HashSet<>();
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < prerequisites.length; i ++) {
int curNum = prerequisites[i][0];
int preNum = prerequisites[i][1];
sum.add(curNum);
sum.add(preNum);
if (!map.containsKey(curNum)) {
map.put(curNum, new LinkedList<>());
}
map.get(curNum).add(preNum);
}
if (sum.size() > numCourses) {
return false;
}
visited = new int[numCourses];
for (Integer key: map.keySet()) {
if (visited[key] == 0) {
dfs(map, key);
}
}
return res;
}
public void dfs(Map<Integer, List<Integer>> map, int start) {
visited[start] = 1;
if (!map.containsKey(start)) {
visited[start] = 2;
return;
}
for (Integer i : map.get(start)) {
if (visited[i] == 1) {
res = false;
return;
}
if (!res) {
return;
}
if (visited[i] == 0) {
dfs(map, i);
}
}
visited[start] = 2;
}
}
代码:bfs
class Solution {
int[] visited;
boolean res = true;
public boolean canFinish(int numCourses, int[][] prerequisites) {
int[] table = new int[numCourses];
Map<Integer, List<Integer>> adj = new HashMap<>();
for (int i = 0; i < numCourses; i ++) {
adj.put(i, new ArrayList<Integer>());
}
for (int i = 0; i < prerequisites.length; i ++) {
int pre = prerequisites[i][0];
int next = prerequisites[i][1];
adj.get(pre).add(next);
table[next] += 1;
}
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i ++) {
if (table[i] == 0) {
queue.add(i);
}
}
while (!queue.isEmpty()) {
int cur = queue.poll();
numCourses --;
for (Integer num : adj.get(cur)) {
table[num] --;
if (table[num] == 0) {
queue.add(num);
}
}
}
return numCourses == 0;
}
}