从始点到终点的所有路径
难度:
标签:
题目描述
代码结果
运行时间: 45 ms, 内存: 19.2 MB
/*
* LeetCode题目: 从始点到终点的所有路径
* 题目思路:
* 使用Java Stream API来实现DFS。
* Stream API不太适合直接进行递归,因此我们还是需要在DFS方法中使用递归。
* 通过Stream API,我们可以更简洁地操作集合。
*/
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class AllPathsFromSourceToTargetStream {
public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
List<List<Integer>> results = new ArrayList<>();
List<Integer> path = new ArrayList<>();
path.add(0);
dfs(graph, 0, path, results);
return results;
}
private void dfs(int[][] graph, int node, List<Integer> path, List<List<Integer>> results) {
if (node == graph.length - 1) {
results.add(new ArrayList<>(path));
return;
}
List<Integer> nextNodes = IntStream.of(graph[node]).boxed().collect(Collectors.toList());
nextNodes.forEach(nextNode -> {
path.add(nextNode);
dfs(graph, nextNode, path, results);
path.remove(path.size() - 1);
});
}
}
解释
方法:
该题解采用了逆向拓扑排序的方法来解决问题。首先,根据输入的边构建了一个逆向的邻接表,即对于每个边(u, v),在邻接表中v指向u。同时,使用一个计数器数组来记录每个节点入边的数量。如果终点destination的入边不为0,直接返回False,因为终点不应该有出边。之后使用一个队列来进行逆向拓扑排序,从终点开始,每次从队列中取出一个节点,检查该节点是否为始点source,是则返回True。对于该节点的每个邻居,减少它的入边计数,并在入边计数为0时将其加入队列。如果队列处理完,始点未被访问到,则返回False。这个方法主要是检查是否存在从source到destination的有效路径。
时间复杂度:
O(V + E)
空间复杂度:
O(V)
代码细节讲解
🦆
在构建逆向邻接表时,为何选择将每个边(u, v)存储为v指向u而不是u指向v?
▷🦆
逆向拓扑排序在此题中的作用是什么?它是如何确保可以找到从起点到终点的有效路径的?
▷🦆
为什么在检查终点destination时,如果其入边不为0则直接返回False?终点在逻辑上应具备什么样的特性?
▷