Most graph problems disguise themselves. 'Number of islands' is a connected-components count. 'Course schedule' is cycle detection on a DAG. The senior skill is reframing the problem in graph language out loud, then picking BFS, DFS, or topological sort with a one-sentence justification.
Q: Number of islands
A 2D grid of '1' and '0'; count connected components of '1's where adjacency is 4-directional. Iterate every cell; when you hit an unvisited '1', start a BFS or DFS, mark every reachable '1' as visited (either flip it to '0' in place or use a visited set), increment the island count. O(m*n) time, O(m*n) space worst case for the queue/recursion. The one-line reframing to say first: 'this is connected components on an implicit grid graph.' Edge cases: empty grid; all water; all land (one island); 1xN or Nx1 strips. The implementation choice — BFS with a queue versus DFS with recursion — has a real tradeoff worth voicing: DFS is shorter to write but blows the stack on large grids (a 1000x1000 of all '1's is 10^6 deep). Senior candidates pick iterative BFS or iterative DFS with an explicit stack for production-grade code. The mutation-vs-visited-set tradeoff: mutating the grid is O(1) extra space but destroys input; visited set is cleaner but O(m*n) extra. Mention both, pick one, justify.
Q: Word ladder — shortest transformation from beginWord to endWord
BFS, because we want shortest path in an unweighted graph where nodes are words and edges connect words differing by one letter. The naive 'compare every pair of words' edge construction is O(N² * L). The trick: build a pattern map where each word maps to all its wildcard patterns ('hot' → '*ot', 'h*t', 'ho*') and use that map during BFS to find neighbors in O(L * 26) per word. O(N * L²) total. Use BFS, not DFS — DFS finds a path, not the shortest. Edge cases: endWord not in the dictionary (return 0); beginWord == endWord (0 or 1 depending on spec — clarify); no path exists (return 0). Bidirectional BFS is the optimization that earns the senior signal: search from both ends simultaneously, terminating when the frontiers meet, which roughly square-roots the visited count. State 'I'd start with single-direction BFS for correctness, then mention bidirectional BFS as the optimization.' That ordering — correctness first, optimization framed as a follow-up — is the experienced engineer's move.
Q: Course schedule — can you finish all courses given prerequisites?
This is cycle detection on a directed graph. Two clean approaches. (1) Kahn's algorithm: compute in-degrees, push all zero-in-degree nodes to a queue, repeatedly pop and decrement neighbors' in-degrees, pushing any that hit zero. If the popped count equals N, the graph is a DAG and you can finish; otherwise a cycle exists. (2) DFS with three-color marking (white/unvisited, gray/in-current-path, black/done): if DFS hits a gray node, you've found a back edge — cycle. Both are O(V+E). The follow-up 'return the order' is Course Schedule II — Kahn's gives the topological order for free; DFS gives reverse postorder. The interview signal: name the abstraction ('this is topological sort / cycle detection on a directed graph') in the first sentence. Edge cases: no prerequisites at all (trivially possible, any order); self-loop (cycle of length 1, impossible); disconnected components (don't forget to start DFS from every unvisited node).
Q: Clone graph — deep copy an undirected graph
BFS or DFS with a hash map from original node to cloned node. The map serves two purposes: it's the visited set and it's how you wire up edges to already-cloned neighbors. On visiting an original node, create its clone if not in the map, then for each neighbor: if cloned already, link to the existing clone; otherwise create the clone, link, and enqueue. O(V+E) time and space. The bug that catches juniors: creating the clone but forgetting to populate its neighbors before another node tries to link to it, leading to incomplete connections. The map-first invariant ('I always put a node in the map before traversing its neighbors') prevents infinite recursion in cycles and prevents duplicate clones. Edge cases: empty graph (return null); single node with no edges; single node with self-loop; fully disconnected graph (the function only clones the component reachable from the input node — clarify whether that's the intent). State the invariant, name the data structure, write it.
Q: Word search — does word exist in 2D grid by adjacent letters?
DFS with backtracking. Iterate every cell as a potential starting point; from each, recurse in 4 directions trying to match the next character of the word. The crucial detail: mark the current cell as visited before recursing (e.g., temporarily set it to '#') and unmark on the way back, so the path can revisit other cells but not itself within a single search. O(m * n * 4^L) time worst case, O(L) recursion depth. Edge cases: empty word (return true or clarify); word longer than total cells (early-return false); first letter not in grid at all (early return). The optimization that scores points: prune by character frequency — if any character in the word appears more often than in the grid, return false immediately. Also: search starting from the rarer end of the word (reverse if the last character is rarer than the first). Senior candidates also note the recursion-stack risk on long words. Clean backtracking style — restore state on the way out, every time — is the readability signal interviewers grade on.