参考:
问题总览
| 序号 | 题目 | 完成 |
|---|---|---|
| 133. 克隆图 |
题解
图的遍历
| 序号 | 题目 | 完成 |
|---|---|---|
| 797. 所有可能的路径 | ✅ | |
| 剑指 Offer II 110. 所有路径 | ✅ |
class Solution {
List<List<Integer>> ans;
public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
int len = graph.length;
ans = new ArrayList<>();
backtrace(graph, 0, new LinkedList<Integer>());
return ans;
}
public void backtrace(int[][] graph, int from, LinkedList<Integer> path) {
path.add(from);
if (from == graph.length - 1) {
ans.add(new ArrayList<>(path));
path.removeLast();
return;
}
int[] toList = graph[from];
for (int to : toList) {
backtrace(graph, to, path);
}
path.removeLast();
}
}
环检测以及拓扑排序
| 序号 | 题目 | 完成 |
|---|---|---|
| 207. 课程表 | ✅ | |
| 210. 课程表 II | ✅ | |
| 剑指 Offer II 113. 课程顺序 | ✅ |
判断节点是否有环。
//DFS解法
class Solution {
// 是否已经遍历过
boolean[] visited;
boolean[] onPath;
// key为当前节点,value为当前节点能到达的所有节点
boolean hasCycle = false;
public boolean canFinish(int numCourses, int[][] prerequisites) {
visited = new boolean[numCourses];
onPath = new boolean[numCourses];
Map<Integer, List<Integer>> paths = new HashMap<>();
for (int[] prerequisite : prerequisites) {
//[0,1]表示,要想到达0必须先到达1,那么说明路径是这样的:1->0
int from = prerequisite[1];
int to = prerequisite[0];
List<Integer> availables = paths.getOrDefault(from, new ArrayList<>());
availables.add(to);
paths.put(from, availables);
}
// 当前
for (int i = 0; i < numCourses; i++) {
traverse(paths,i);
}
return !hasCycle;
}
public void traverse(Map<Integer, List<Integer>> paths, int from) {
// 如果路径上的节点已经被遍历过,那说明存在环
if (onPath[from]) {
hasCycle = true;
return;
}
// 当前节点已经遍历过
if (visited[from]) {
return;
}
// visited就代表遍历过的节点,不需要再置为false
visited[from] = true;
onPath[from] = true;
List<Integer> availables = paths.get(from);
if (availables != null && availables.size() > 0) {
for (int to : availables) {
traverse(paths, to);
}
}
onPath[from] = false;
}
}
//leetcode submit region end(Prohibit modification and deletion)
打印出可行的路径。
// DFS解法
class Solution {
boolean[] onPath;
boolean[] visited;
LinkedList<Integer> trace;
boolean hasCycle = false;
public int[] findOrder(int numCourses, int[][] prerequisites) {
onPath = new boolean[numCourses];
visited = new boolean[numCourses];
trace = new LinkedList<>();
Map<Integer, List<Integer>> graph = new HashMap<>();
for (int[] prerequisite : prerequisites) {
//[0,1]表示,要想到达0必须先到达1,那么说明路径是这样的:1->0
int from = prerequisite[1];
int to = prerequisite[0];
List<Integer> availables = graph.getOrDefault(from, new ArrayList<>());
availables.add(to);
graph.put(from, availables);
}
// 当前
for (int i = 0; i < numCourses; i++) {
traverse(graph, i);
}
if (hasCycle) {
return new int[]{};
}
int[] res = new int[numCourses];
Collections.reverse(trace);
for (int i = 0; i < numCourses; i++) {
res[i] = trace.get(i);
}
return res;
}
public void traverse(Map<Integer, List<Integer>> graph, int from) {
// 如果路径上的节点已经被遍历过,那说明存在环
if (onPath[from]) {
hasCycle = true;
return;
}
// 当前节点已经遍历过
if (visited[from]) {
return;
}
// visited就代表遍历过的节点,不需要再置为false
visited[from] = true;
onPath[from] = true;
List<Integer> availables = graph.get(from);
if (availables != null && availables.size() > 0) {
for (int to : availables) {
traverse(graph, to);
}
}
onPath[from] = false;
// 记录走过的路径
trace.add(from);
}
}