Description 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. Solutions Solution 1: DFS First, we construct an adjacency list \(g\) based on the given graph, where \(g[i]\) represents all the neighboring nodes of node \(i\) . We use a hash table or array \(vis\) to record the visited nodes, and then start a depth-first search from node \(start\) . If we search to node \(target\) , we return true, otherwise we return false.
The process of depth-first search is as follows:
If the current node \(i\) equals the target node \(target\) , return true. If the current node \(i\) has been visited, return false. Otherwise, mark the current node \(i\) as visited, and then traverse all the neighboring nodes \(j\) of node \(i\) , and recursively search node \(j\) . The time complexity is \(O(n + m)\) , and the space complexity is \(O(n + m)\) , where \(n\) and \(m\) are the number of nodes and edges respectively.
Python3 Java C++ Go TypeScript Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 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 )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 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 ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 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 ]);
}
auto dfs = [ & ]( this auto && dfs , int i ) -> bool {
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 );
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 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 )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 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 );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 class Solution {
private var g : [[ Int ]] !
private var vis : [ Bool ] !
private var target : Int !
func findWhetherExistsPath ( _ n : Int , _ graph : [[ Int ]], _ start : Int , _ target : Int ) -> Bool {
vis = [ Bool ]( repeating : false , count : n )
g = [[ Int ]]( repeating : [], count : n )
self . target = target
for e in graph {
g [ e [ 0 ]]. append ( e [ 1 ])
}
return dfs ( start )
}
private func dfs ( _ i : Int ) -> Bool {
if i == target {
return true
}
if vis [ i ] {
return false
}
vis [ i ] = true
for j in g [ i ] {
if dfs ( j ) {
return true
}
}
return false
}
}
Solution 2: BFS Similar to Solution 1, we first construct an adjacency list \(g\) based on the given graph, where \(g[i]\) represents all the neighboring nodes of node \(i\) . We use a hash table or array \(vis\) to record the visited nodes, and then start a breadth-first search from node \(start\) . If we search to node \(target\) , we return true, otherwise we return false.
The time complexity is \(O(n + m)\) , and the space complexity is \(O(n + m)\) , where \(n\) and \(m\) are the number of nodes and edges respectively.
Python3 Java C++ Go TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 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 ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 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 ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 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 ;
}