Command Palette

Search for a command to run...

Problem 20.3 · Graph FundamentalsEasy

Find if Path Exists in Graph

What it teaches: The first traversal: build an adjacency list, then explore from the source with a visited array.

Practise it on judges as “Find if Path Exists in Graph”.

The problem

Given an undirected graph with n nodes (0..n−1) and an edge list, return true if there is a path from source to destination.

Example 1

Input: n = 3, edges = [[0,1],[1,2],[2,0]], source = 0, destination = 2
Output: true

Constraints

  • 1 ≤ n ≤ 2 × 10⁵
  • 0 ≤ edges ≤ 2 × 10⁵

Pattern clues in the wording

  • → "Is there a path" = reachability

These clues point to Graph BFS: Explore from a start node in rings of increasing distance using a queue and a visited set.

Stuck? Take one hint at a time

Solution.java · starter
import java.util.*;

class Solution {
    public boolean validPath(int n, int[][] edges, int source, int destination) {
        return false;
    }
}

Write your solution locally or in your editor for now. The in-browser runner (Java first, then Python, C++ and more) will run these tests right here.

Test cases

#InputExpected
1
n = 3
edges = [[0,1],[1,2],[2,0]]
source = 0
destination = 2
true
2
n = 6
edges = [[0,1],[0,2],[3,5],[5,4],[4,3]]
source = 0
destination = 5
false

+ 1 hidden test the code runner will check

From slow to fast

Approaches

1

BFS with visited

Time O(V + E) Space O(V + E)

Queue the source and mark it. Pop nodes; if a node is the destination, return true; otherwise queue its unvisited neighbours.

Approach 1
import java.util.*;

class Solution {
    public boolean validPath(int n, int[][] edges, int source, int destination) {
        List<List<Integer>> adj = new ArrayList<>();
        for (int i = 0; i < n; i++) adj.add(new ArrayList<>());
        for (int[] e : edges) { adj.get(e[0]).add(e[1]); adj.get(e[1]).add(e[0]); }
        boolean[] seen = new boolean[n];
        Deque<Integer> q = new ArrayDeque<>();
        q.offer(source);
        seen[source] = true;
        while (!q.isEmpty()) {
            int u = q.poll();
            if (u == destination) return true;
            for (int v : adj.get(u)) if (!seen[v]) { seen[v] = true; q.offer(v); }
        }
        return false;
    }
}

Verdict: The template for every reachability question.

2

Union-find

Time O((V + E) α(V)) Space O(V)

Union the endpoints of every edge, then check whether source and destination share a root.

Approach 2
class Solution {
    private int[] parent;

    public boolean validPath(int n, int[][] edges, int source, int destination) {
        parent = new int[n];
        for (int i = 0; i < n; i++) parent[i] = i;
        for (int[] e : edges) parent[find(e[0])] = find(e[1]);
        return find(source) == find(destination);
    }

    private int find(int x) {
        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }
        return x;
    }
}

Verdict: No adjacency list needed; preview of Module 25.

Before you submit

Edge cases and common mistakes

Test these inputs

  • source == destination
  • No edges
  • Disconnected graph

Mistakes people make

  • Forgetting the visited array (infinite loop on cycles).
  • Marking visited when popping instead of when pushing (duplicates in the queue).

Interview

Follow-up questions

When is union-find the better choice?