节点间通路
难度:
标签:
题目描述
Given a directed graph, design an algorithm to find out whether there is a route between two nodes.
Example1:
Input: n = 3, graph = [[0, 1], [0, 2], [1, 2], [1, 2]], start = 0, target = 2 Output: true
Example2:
Input: n = 5, graph = [[0, 1], [0, 2], [0, 4], [0, 4], [0, 1], [1, 3], [1, 4], [1, 3], [2, 3], [3, 4]], start = 0, target = 4 Output true
Note:
0 <= n <= 100000
- All node numbers are within the range [0, n].
- There might be self cycles and duplicated edges.
代码结果
运行时间: 89 ms, 内存: 53.4 MB
/*
* 题目思路:
* 使用Java Stream进行图的DFS实现。通过流式处理减少显式循环的使用。
* 通过递归的方式来检查从起始节点到目标节点是否存在路径。
*/
import java.util.*;
import java.util.stream.*;
public class SolutionStream {
public boolean hasPath(int n, int[][] graph, int start, int target) {
// 使用邻接表表示图
Map<Integer, List<Integer>> adjList = Arrays.stream(graph)
.collect(Collectors.groupingBy(
edge -> edge[0],
Collectors.mapping(edge -> edge[1], Collectors.toList())));
// 标记节点是否访问过
boolean[] visited = new boolean[n];
return dfs(adjList, visited, start, target);
}
private boolean dfs(Map<Integer, List<Integer>> adjList, boolean[] visited, int current, int target) {
if (current == target) {
return true;
}
visited[current] = true;
return adjList.getOrDefault(current, Collections.emptyList()).stream()
.filter(neighbor -> !visited[neighbor])
.anyMatch(neighbor -> dfs(adjList, visited, neighbor, target));
}
}
解释
方法:
该题解采用了深度优先搜索(DFS)的算法来解决有向图中两个节点之间是否存在路径的问题。首先,构建邻接表来表示图,这由列表 `next` 表示,其中 `next[i]` 包含所有从节点 i 可以直接到达的节点。使用一个标志数组 `flag` 来记录每个节点是否已被访问过,以避免循环访问和重复工作。从起始节点 `start` 开始,使用栈(这里的实现使用列表的 pop 方法模拟栈)来进行深度优先搜索。每次从栈中取出一个节点,检查其所有邻接节点;如果邻接节点是目标节点 `target`,则立即返回 true 表示路径存在。如果不是目标节点且未被访问过,则将其加入栈中并标记为已访问。如果所有可能的路径都检查完毕,栈为空,则返回 false 表示没有路径。
时间复杂度:
O(n + m)
空间复杂度:
O(n + m)
代码细节讲解
🦆
为什么选择深度优先搜索(DFS)而不是广度优先搜索(BFS)来解决这个问题?
▷🦆
在构建邻接表时,如果存在重复的边(如示例输入中的 [1, 2], [1, 2]),这对算法的执行有什么影响?是否需要在建图时去除重复的边?
▷🦆
算法中使用的标志数组 `flag` 仅包含两种状态(未访问和已访问),能否在这个场景中使用颜色标记法(如使用三种颜色标记未访问、正在访问、已访问完成)来帮助检测有向图中的环?
▷