Graphs

Networks of nodes and edges

Graph Representations & Traversals

Graphs model relationships between entities. They can be directed/undirected, weighted/unweighted, cyclic/acyclic. Graphs appear in social networks, maps, dependency resolution, and countless interview problems.

Graph Types

typescript
// Graph Implementation & BFS/DFS
// Adjacency List representation
class Graph {
  private adj = new Map<string, string[]>();

  addEdge(u: string, v: string, directed = false): void {
    if (!this.adj.has(u)) this.adj.set(u, []);
    this.adj.get(u)!.push(v);
    if (!directed) {
      if (!this.adj.has(v)) this.adj.set(v, []);
      this.adj.get(v)!.push(u);
    }
  }

  // BFS — O(V + E) — Level-order, shortest path in unweighted
  bfs(start: string): string[] {
    const visited = new Set<string>([start]);
    const queue = [start];
    const result: string[] = [];
    while (queue.length) {
      const node = queue.shift()!;
      result.push(node);
      for (const neighbor of this.adj.get(node) || []) {
        if (!visited.has(neighbor)) {
          visited.add(neighbor);
          queue.push(neighbor);
        }
      }
    }
    return result;
  }

  // DFS — O(V + E) — Path finding, cycle detection
  dfs(start: string): string[] {
    const visited = new Set<string>();
    const result: string[] = [];
    const visit = (node: string) => {
      visited.add(node);
      result.push(node);
      for (const neighbor of this.adj.get(node) || []) {
        if (!visited.has(neighbor)) visit(neighbor);
      }
    };
    visit(start);
    return result;
  }
}

// Number of Islands — Classic BFS/DFS
function numIslands(grid: string[][]): number {
  const rows = grid.length, cols = grid[0].length;
  let count = 0;
  
  function dfs(r: number, c: number): void {
    if (r < 0 || r >= rows || c < 0 || c >= cols || grid[r][c] === '0') return;
    grid[r][c] = '0'; // mark visited
    dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1);
  }
  
  for (let r = 0; r < rows; r++) {
    for (let c = 0; c < cols; c++) {
      if (grid[r][c] === '1') { count++; dfs(r, c); }
    }
  }
  return count;
}

💬 When do you use BFS vs DFS?

Use BFS for shortest path in unweighted graphs, level-order traversal, and when the solution is close to the root. Use DFS for topological sorting, cycle detection, path finding, and when you need to explore all possibilities (backtracking). BFS uses more memory (queue) while DFS uses the call stack.