Find if Path Exists in Graph
Build an adjacency list: for each edge [u, v], put v in the list of u and u in the list of v. Then run BFS from source, marking each node when it is pushed. A node is marked exactly when it can be reached, so the answer is the mark on destination.
A node counts as reached only when a walk from source to it exists, so a node gets marked only when it is one edge away from a node that is already reached.
Problem
You are given n nodes numbered 0 to n − 1, and a list of edges. Each edge [u, v] joins node u and node v, and it works in both directions.
You are also given a source node and a destination node. Return true if you can walk from source to destination along the edges, and false if you cannot.
An integer n, a list edges where each entry is a pair [u, v], and two node numbers source and destination.
true if a walk from source to destination exists, otherwise false.
There are two ways to get from 0 to 2: the direct edge 2–0, or the walk 0 → 1 → 2.
Nodes 0, 1 and 2 form one group, and nodes 3, 4 and 5 form another. No edge joins the two groups, so 5 cannot be reached from 0.
- • 1 ≤ n ≤ 2 · 10^5
- • 0 ≤ edges.length ≤ 2 · 10^5
- • edges[i].length = 2, with 0 ≤ u, v ≤ n − 1 and u ≠ v
- • There are no duplicate edges.
- • 0 ≤ source, destination ≤ n − 1
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
If I stand on
source, which nodes can I step to right away? Which nodes can I reach from those? - 2.
An edge
[u, v]works both ways. What should I store for each node so I can find its neighbours quickly? - 3.
Does the question ask for the shortest walk, or only whether a walk exists?
- 4.
If I keep a record of the nodes I have already reached, how do I stop myself from walking in circles?
- 5.
When I have explored everything reachable from the source, what does that set look like if the destination is not in it?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Keep marking new nodes by scanning every edge again and again until nothing changes | O(V · E) | O(V) |
| Optimal | Build a neighbour list once, then one BFS from the source; the answer is whether the destination was visited | O(V + E) | O(V + E) |
Why does this belong to this pattern?
- “Can you get from A to B”A yes-or-no question about connection, not a shortest path. A plain reachability search is enough.
- “edges work in both directions”Each edge goes into the neighbour list of both ends. Forgetting one side breaks the search.
- “nodes labelled 0 to n − 1”The visited marks can be a plain array indexed by the node label.
The question asks whether one node can reach another, so the search only needs a yes or no. The move is the same in every connectivity problem: build an adjacency list once, then run one traversal from the source, which marks everything in its group. This is the anchor of the sub-pattern, because the edges are two-way and there is only one source. The next questions change the input: Keys and Rooms makes the edges one-way, and Number of Provinces asks how many groups there are.
Don't make this mistake
Take the edges [[1,0],[1,2]] with source 0 and destination 2. The answer is true (0 → 1 → 2). With only one direction, only adj[1] gets entries and list 0 stays empty. BFS from 0 finds nothing, so the code returns false.
Being one edge away is not the same as being reachable. On the dry run, adj[0] = [1, 5] does not contain 4, so this code returns false. The walk 0 → 1 → 2 → 3 → 4 has four edges, so the answer is true.
Nothing stops a node from being pushed again. On the dry run, node 0 pushes 1, node 1 pushes 0 back, and 0 pushes 1 again. The queue never empties.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Graph BFS / DFS translate into production architectures and low-level memory mechanics.