How to Solve LeetCode Graph Problems in JavaScript

2025-08-07

Graph problems are everywhere on LeetCode, and they often intimidate developers preparing for interviews. The truth is, once you understand the core techniques — traversal, BFS, DFS, and Union-Find — most graph questions become patterns you can recognize and apply.

In this post, we’ll go step by step through common graph problems, show JavaScript solutions, and outline the thought process that interviewers want to hear.


Step 1: Know your graph representations

On LeetCode, graphs usually show up in one of three forms:

  1. Adjacency list[[1,2], [0,2], [0,1,3], [2]]
  2. Edge list[[0,1], [1,2], [2,3]]
  3. Matrix[[0,1,0], [1,0,1], [0,1,0]]

Converting between them is often your first step. For most problems, you’ll build an adjacency list with a Map or object in JavaScript for fast traversal.


Step 2: Breadth-First Search (BFS)

BFS explores neighbors level by level. It’s great for shortest path problems in an unweighted graph.

Example: Number of Connected Components in an Undirected Graph

function countComponents(n, edges) {
  const adj = new Map();
  for (let i = 0; i < n; i++) adj.set(i, []);
  for (const [u, v] of edges) {
    adj.get(u).push(v);
    adj.get(v).push(u);
  }

  const visited = new Set();
  let count = 0;

  for (let i = 0; i < n; i++) {
    if (!visited.has(i)) {
      count++;
      const queue = [i];
      visited.add(i);
      while (queue.length) {
        const node = queue.shift();
        for (const nei of adj.get(node)) {
          if (!visited.has(nei)) {
            visited.add(nei);
            queue.push(nei);
          }
        }
      }
    }
  }
  return count;
}

Step 3: Depth-First Search (DFS)

DFS is ideal for exploring deep paths, detecting cycles, and working with recursive backtracking problems.

Example: Clone Graph

function cloneGraph(node) {
  if (!node) return null;
  const map = new Map();

  function dfs(curr) {
    if (map.has(curr)) return map.get(curr);
    const copy = { val: curr.val, neighbors: [] };
    map.set(curr, copy);
    for (const nei of curr.neighbors) {
      copy.neighbors.push(dfs(nei));
    }
    return copy;
  }

  return dfs(node);
}

Here recursion handles traversal while a map prevents infinite loops in cyclic graphs.


Step 4: Union-Find (Disjoint Set Union)

Union-Find is the go-to for connectivity problems. You’ll see it in problems like detecting cycles or counting components.

Example: Redundant Connection

function findRedundantConnection(edges) {
  const parent = Array(2001).fill(0).map((_, i) => i);

  function find(x) {
    if (parent[x] !== x) parent[x] = find(parent[x]);
    return parent[x];
  }

  function union(x, y) {
    const rootX = find(x);
    const rootY = find(y);
    if (rootX === rootY) return false;
    parent[rootX] = rootY;
    return true;
  }

  for (const [u, v] of edges) {
    if (!union(u, v)) return [u, v];
  }
}

Step 5: Weighted graphs and shortest paths

For weighted graphs, you’ll need Dijkstra’s algorithm.

Example: Network Delay Time

function networkDelayTime(times, n, k) {
  const adj = new Map();
  for (let i = 1; i <= n; i++) adj.set(i, []);
  for (const [u, v, w] of times) {
    adj.get(u).push([v, w]);
  }

  const dist = Array(n + 1).fill(Infinity);
  dist[k] = 0;

  const pq = [[0, k]]; // [time, node]

  while (pq.length) {
    pq.sort((a, b) => a[0] - b[0]); // simple priority queue
    const [time, node] = pq.shift();
    if (time > dist[node]) continue;
    for (const [nei, w] of adj.get(node)) {
      if (time + w < dist[nei]) {
        dist[nei] = time + w;
        pq.push([dist[nei], nei]);
      }
    }
  }

  const max = Math.max(...dist.slice(1));
  return max === Infinity ? -1 : max;
}

This shows how you can implement Dijkstra with just arrays in JavaScript, though in production you’d use a real priority queue.


Step 6: Recognize patterns

Most LeetCode graph problems fall into these buckets:

  • Traversal (BFS/DFS): Is there a path, count islands, clone graph.
  • Connectivity (Union-Find): Count components, detect cycles.
  • Shortest path: Dijkstra, Bellman-Ford, Floyd-Warshall.
  • Topological sort: Course Schedule, Alien Dictionary.

Once you recognize the category, you can jump straight into the right approach.


Tips for interviews

  • Restate the problem and identify if it’s unweighted (BFS) or weighted (Dijkstra).
  • Draw a small example and talk through the traversal.
  • Mention complexity (O(V+E) for BFS/DFS).
  • Be clear about visited sets to avoid infinite loops.
  • Practice edge cases (empty graph, disconnected graph).

Wrap up

Graph problems in JavaScript may look overwhelming at first, but once you have BFS, DFS, and Union-Find under your belt, you’ll start to see how similar many questions really are.

If you want a tool that can give you a working graph solution mid-practice when you’re stuck, check out StealthCoder. It lets you capture the problem and instantly get an explanation plus code, so you can learn the patterns faster.