Skip to content
DSA Grind
All 26 sections

Blind 75 — Graph Pattern Guide

Pattern guideUpdated
On this page

How to Identify a “Graph” Problem

Interview Triggers

  • Nodes + edges, adjacency list/matrix
  • “Connected components”, “is it connected”, “is there a cycle”
  • “Course schedule” / dependency order → topological sort
  • 2-D grid where cells are nodes (LC 200, 417)
  • “Clone / copy the graph”
  • Words → graph (alien dictionary)

Which Sub-Pattern Does It Belong To?

If the prompt says… Use this sub-pattern Example LC
“Deep copy a graph” BFS/DFS + HashMap clone 133
“Can finish all courses given prerequisites?” Topological sort / cycle detect 207
“Cells that can flow to both oceans” Multi-source reverse DFS/BFS 417
“Count islands in a grid” Flood fill (DFS/BFS) 200
“Longest consecutive run of numbers” HashSet + start-of-sequence 128
“Words form a valid dictionary order” Topological sort from letters 269
“Is this edge list a valid tree?” Union-Find + n-1 edges 261
“Count connected components” Union-Find or DFS 323

The Decision Tree

GRAPH PROBLEM

├─ Shortest path / level-order info?
│   └─ BFS (LC 102 tree, LC 200 grid)

├─ Need to visit all reachable nodes?
│   └─ DFS (LC 200, 133, 417)

├─ Dependency / ordering?
│   └─ Topological sort (Kahn's BFS or DFS) → LC 207, 269

├─ Connectivity / merge groups?
│   └─ Union-Find (DSU) → LC 261, 323

├─ Cycle detection?
│   ├─ Directed   → DFS color states (white/gray/black) or Kahn's
│   └─ Undirected → Union-Find or DFS parent tracking

└─ 2-D grid → treat each cell as a node
    └─ Flood fill = DFS/BFS (LC 200)

Traversal Templates

DFS (Recursive)

void dfs(int node, boolean[] visited, List<List<Integer>> adj) {
    if (visited[node]) return;
    visited[node] = true;
    for (int neighbor : adj.get(node)) dfs(neighbor, visited, adj);
}

BFS (Queue)

void bfs(int start, List<List<Integer>> adj) {
    Queue<Integer> q = new ArrayDeque<>();
    boolean[] visited = new boolean[adj.size()];
    q.offer(start); visited[start] = true;
    while (!q.isEmpty()) {
        int node = q.poll();
        for (int neighbor : adj.get(node)) {
            if (!visited[neighbor]) { visited[neighbor] = true; q.offer(neighbor); }
        }
    }
}

Topological Sort (Kahn’s)

int[] indegree = new int[n];
// build indegree from edges
Queue<Integer> q = new ArrayDeque<>();
for (int i = 0; i < n; i++) if (indegree[i] == 0) q.offer(i);
int count = 0;
while (!q.isEmpty()) {
    int u = q.poll(); count++;
    for (int v : adj.get(u)) if (--indegree[v] == 0) q.offer(v);
}
return count == n; // false = cycle exists

Union-Find (DSU)

int[] parent;
int find(int x) { return parent[x] == x ? x : (parent[x] = find(parent[x])); }
boolean union(int a, int b) {
    int ra = find(a), rb = find(b);
    if (ra == rb) return false;
    parent[ra] = rb;
    return true;
}

Bread & Butter Problems

# Problem LC # Difficulty Sub-Pattern
1 Number of Islands 200 Medium Flood fill
2 Clone Graph 133 Medium DFS/BFS + Map
3 Course Schedule 207 Medium Topo sort

FAANG “Aha!” Problems

# Problem LC # Difficulty Sub-Pattern
1 Pacific Atlantic Water Flow 417 Medium Multi-source DFS
2 Longest Consecutive Sequence 128 Medium HashSet streak
3 Graph Valid Tree 261 Medium Union-Find
4 Number of Connected Components 323 Medium Union-Find / DFS
5 Alien Dictionary 269 Hard Topo sort

Java Implementation Tips

  • Adjacency list: List<List<Integer>> adj — initialize with for (int i=0;i<n;i++) adj.add(new ArrayList<>());
  • Use ArrayDeque over LinkedList for queue — faster, no nulls allowed.
  • For recursive DFS on deep graphs, watch stack depth (~10^4 in Java). Convert to iterative if needed.
  • Visited tracking: boolean[] (faster) over Set<Integer>.
  • For grid problems, use direction array: int[][] dirs = {{0,1},{1,0},{0,-1},{-1,0}};

Senior Mental Trigger

“Level-by-level → BFS. Explore-everything → DFS. Ordering → Topo. Grouping → Union-Find.”