LeetCode Problem Workspace
Find if Path Exists in Graph
Determine if a valid path exists between two vertices in a bi-directional graph using traversal techniques.
4
Topics
6
Code langs
3
Related
Practice Focus
Easy · Graph traversal with depth-first search
Answer-first summary
Determine if a valid path exists between two vertices in a bi-directional graph using traversal techniques.
Ace coding interviews with Interview AiBoxInterview AiBox guidance for Graph traversal with depth-first search
This problem requires checking whether a path exists from a source vertex to a destination vertex in an undirected graph. Use depth-first search, breadth-first search, or union-find to explore connectivity. The solution efficiently handles cycles and disconnected components while ensuring correctness for large graphs.
Problem Statement
You are given an undirected graph with n vertices labeled from 0 to n - 1. The graph is represented as a list of bi-directional edges, where each edge connects two distinct vertices. No edge appears more than once, and no vertex connects to itself.
Given the graph edges and two vertices, source and destination, determine if a valid path exists from the source vertex to the destination vertex. Return true if such a path exists, otherwise return false.
Examples
Example 1
Input: n = 3, edges = [[0,1],[1,2],[2,0]], source = 0, destination = 2
Output: true
There are two paths from vertex 0 to vertex 2:
- 0 → 1 → 2
- 0 → 2
Example 2
Input: n = 6, edges = [[0,1],[0,2],[3,5],[5,4],[4,3]], source = 0, destination = 5
Output: false
There is no path from vertex 0 to vertex 5.
Constraints
- 1 <= n <= 2 * 105
- 0 <= edges.length <= 2 * 105
- edges[i].length == 2
- 0 <= ui, vi <= n - 1
- ui != vi
- 0 <= source, destination <= n - 1
- There are no duplicate edges.
- There are no self edges.
Solution Approach
Depth-First Search (DFS)
Implement DFS starting from the source vertex. Recursively visit all connected neighbors while marking visited vertices. If the destination is reached during traversal, return true; otherwise, return false after exploring all reachable nodes.
Breadth-First Search (BFS)
Use a queue to perform BFS from the source vertex. Add neighbors of each vertex to the queue while tracking visited vertices. If the destination vertex is dequeued, return true. If the queue empties without reaching destination, return false.
Union-Find Approach
Initialize a union-find structure to group connected components. Union vertices for each edge. After processing all edges, check if the source and destination belong to the same connected component. If yes, return true; otherwise, return false.
Complexity Analysis
| Metric | Value |
|---|---|
| Time | Depends on the final approach |
| Space | Depends on the final approach |
DFS and BFS both run in O(V + E) time and O(V + E) space, where V is vertices and E is edges. Union-Find with path compression and union by rank runs in near O(V + E) time and O(V) space. All approaches efficiently handle sparse or dense graphs without redundant traversal.
What Interviewers Usually Probe
- Expect optimized traversal without revisiting nodes in DFS or BFS.
- Union-Find may indicate awareness of connected components instead of explicit search.
- Handling edge cases with disconnected nodes is important to confirm correct path detection.
Common Pitfalls or Variants
Common pitfalls
- Failing to mark visited nodes, causing infinite recursion in cycles.
- Confusing directed and undirected edges, leading to missing valid paths.
- Assuming all nodes are connected, resulting in incorrect true returns for disconnected graphs.
Follow-up variants
- Check for shortest path existence or length between source and destination.
- Detect if multiple distinct paths exist between two vertices.
- Handle directed graphs instead of undirected graphs for path existence.
FAQ
What is the best approach for 'Find if Path Exists in Graph' for large graphs?
DFS or BFS are straightforward for connected components, while Union-Find efficiently checks connectivity without full traversal.
Does the graph being undirected change the traversal method?
Yes, both DFS and BFS treat edges as bi-directional, so neighbors are explored in both directions.
How do I avoid infinite loops in DFS on this graph problem?
Track visited vertices to prevent revisiting nodes, which is critical in graphs with cycles.
Can I use BFS instead of DFS for this problem?
Absolutely, BFS is equally valid and may find the shortest path faster if required.
What are typical constraints I need to consider?
Vertex count up to 2*10^5, no duplicate edges, no self-loops, and edges can be zero length.
Solution
Solution 1: DFS
We first convert $\textit{edges}$ into an adjacency list $g$, then use DFS to determine whether there is a path from $\textit{source}$ to $\textit{destination}$.
class Solution:
def validPath(
self, n: int, edges: List[List[int]], source: int, destination: int
) -> bool:
def dfs(i: int) -> bool:
if i == destination:
return True
vis.add(i)
for j in g[i]:
if j not in vis and dfs(j):
return True
return False
g = [[] for _ in range(n)]
for u, v in edges:
g[u].append(v)
g[v].append(u)
vis = set()
return dfs(source)Solution 2: BFS
We can also use BFS to determine whether there is a path from $\textit{source}$ to $\textit{destination}$.
class Solution:
def validPath(
self, n: int, edges: List[List[int]], source: int, destination: int
) -> bool:
def dfs(i: int) -> bool:
if i == destination:
return True
vis.add(i)
for j in g[i]:
if j not in vis and dfs(j):
return True
return False
g = [[] for _ in range(n)]
for u, v in edges:
g[u].append(v)
g[v].append(u)
vis = set()
return dfs(source)Solution 3: Union-Find
Union-Find is a tree-like data structure that, as the name suggests, is used to handle some disjoint set **merge** and **query** problems. It supports two operations:
class Solution:
def validPath(
self, n: int, edges: List[List[int]], source: int, destination: int
) -> bool:
def dfs(i: int) -> bool:
if i == destination:
return True
vis.add(i)
for j in g[i]:
if j not in vis and dfs(j):
return True
return False
g = [[] for _ in range(n)]
for u, v in edges:
g[u].append(v)
g[v].append(u)
vis = set()
return dfs(source)Continue Topic
depth first search
Practice more edge cases under the same topic.
arrow_forwardauto_awesomeContinue Pattern
Graph traversal with depth-first search
Expand the same solving frame across more problems.
arrow_forwardsignal_cellular_altSame Difficulty Track
Easy
Stay on this level to stabilize interview delivery.
arrow_forward