节点间通路。给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。
示例1:
输入:n = 3, graph = [[0, 1], [0, 2], [1, 2], [1, 2]], start = 0, target = 2 输出:true
示例2:
输入: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 输出 true
提示:
- 节点数量n在[0, 1e5]范围内。
- 节点编号大于等于 0 小于 n。
- 图中可能存在自环和平行边。
我们先根据给定的图构建一个邻接表 true
,否则返回 false
。
深度优先搜索的过程如下:
- 如果当前节点
$i$ 等于目标节点$target$ ,返回true
; - 如果当前节点
$i$ 已经访问过,返回false
; - 否则,将当前节点
$i$ 标记为已访问,然后遍历节点$i$ 的所有邻居节点$j$ ,递归地搜索节点$j$ 。
时间复杂度
class Solution:
def findWhetherExistsPath(
self, n: int, graph: List[List[int]], start: int, target: int
) -> bool:
def dfs(i: int):
if i == target:
return True
if i in vis:
return False
vis.add(i)
return any(dfs(j) for j in g[i])
g = [[] for _ in range(n)]
for a, b in graph:
g[a].append(b)
vis = set()
return dfs(start)
class Solution {
private List<Integer>[] g;
private boolean[] vis;
private int target;
public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) {
vis = new boolean[n];
g = new List[n];
this.target = target;
Arrays.setAll(g, k -> new ArrayList<>());
for (int[] e : graph) {
g[e[0]].add(e[1]);
}
return dfs(start);
}
private boolean dfs(int i) {
if (i == target) {
return true;
}
if (vis[i]) {
return false;
}
vis[i] = true;
for (int j : g[i]) {
if (dfs(j)) {
return true;
}
}
return false;
}
}
class Solution {
public:
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
vector<int> g[n];
vector<bool> vis(n);
for (auto& e : graph) {
g[e[0]].push_back(e[1]);
}
function<bool(int)> dfs = [&](int i) {
if (i == target) {
return true;
}
if (vis[i]) {
return false;
}
vis[i] = true;
for (int j : g[i]) {
if (dfs(j)) {
return true;
}
}
return false;
};
return dfs(start);
}
};
func findWhetherExistsPath(n int, graph [][]int, start int, target int) bool {
g := make([][]int, n)
vis := make([]bool, n)
for _, e := range graph {
g[e[0]] = append(g[e[0]], e[1])
}
var dfs func(int) bool
dfs = func(i int) bool {
if i == target {
return true
}
if vis[i] {
return false
}
vis[i] = true
for _, j := range g[i] {
if dfs(j) {
return true
}
}
return false
}
return dfs(start)
}
function findWhetherExistsPath(
n: number,
graph: number[][],
start: number,
target: number,
): boolean {
const g: number[][] = Array.from({ length: n }, () => []);
const vis: boolean[] = Array.from({ length: n }, () => false);
for (const [a, b] of graph) {
g[a].push(b);
}
const dfs = (i: number): boolean => {
if (i === target) {
return true;
}
if (vis[i]) {
return false;
}
vis[i] = true;
return g[i].some(dfs);
};
return dfs(start);
}
与方法一类似,我们先根据给定的图构建一个邻接表 true
,否则返回 false
。
时间复杂度
class Solution:
def findWhetherExistsPath(
self, n: int, graph: List[List[int]], start: int, target: int
) -> bool:
g = [[] for _ in range(n)]
for a, b in graph:
g[a].append(b)
vis = {start}
q = deque([start])
while q:
i = q.popleft()
if i == target:
return True
for j in g[i]:
if j not in vis:
vis.add(j)
q.append(j)
return False
class Solution {
public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) {
List<Integer>[] g = new List[n];
Arrays.setAll(g, k -> new ArrayList<>());
boolean[] vis = new boolean[n];
for (int[] e : graph) {
g[e[0]].add(e[1]);
}
Deque<Integer> q = new ArrayDeque<>();
q.offer(start);
vis[start] = true;
while (!q.isEmpty()) {
int i = q.poll();
if (i == target) {
return true;
}
for (int j : g[i]) {
if (!vis[j]) {
q.offer(j);
vis[j] = true;
}
}
}
return false;
}
}
class Solution {
public:
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
vector<int> g[n];
vector<bool> vis(n);
for (auto& e : graph) {
g[e[0]].push_back(e[1]);
}
queue<int> q{{start}};
vis[start] = true;
while (!q.empty()) {
int i = q.front();
q.pop();
if (i == target) {
return true;
}
for (int j : g[i]) {
if (!vis[j]) {
q.push(j);
vis[j] = true;
}
}
}
return false;
}
};
func findWhetherExistsPath(n int, graph [][]int, start int, target int) bool {
g := make([][]int, n)
vis := make([]bool, n)
for _, e := range graph {
g[e[0]] = append(g[e[0]], e[1])
}
q := []int{start}
vis[start] = true
for len(q) > 0 {
i := q[0]
q = q[1:]
if i == target {
return true
}
for _, j := range g[i] {
if !vis[j] {
vis[j] = true
q = append(q, j)
}
}
}
return false
}
function findWhetherExistsPath(
n: number,
graph: number[][],
start: number,
target: number,
): boolean {
const g: number[][] = Array.from({ length: n }, () => []);
const vis: boolean[] = Array.from({ length: n }, () => false);
for (const [a, b] of graph) {
g[a].push(b);
}
const q: number[] = [start];
vis[start] = true;
while (q.length > 0) {
const i = q.pop()!;
if (i === target) {
return true;
}
for (const j of g[i]) {
if (!vis[j]) {
vis[j] = true;
q.push(j);
}
}
}
return false;
}