Graph day โ Course Schedule, Clone Graph, and Word Ladder, with the full follow-up tree on each. Notes:
- Course Schedule's BFS (Kahn's algorithm) doesn't check for cycles directly โ it's inferred afterward. A course stuck in a cycle can never reach
inDegree == 0, because whatever would unlock it is trapped in the same cycle inDegree[nextCourse] -= 1, neverinDegree[course]โ the course you just popped already earned its zero; it's the next course that just lost a dependency- DFS cycle detection needs
path(still on my current call stack) separate fromvisited(cleared elsewhere) โ a single visited set can't tell those apart, and a diamond-shaped DAG (0โ1โ3,0โ2โ3) proves it:3gets visited twice with zero cycles involved - Clone Graph's dictionary isn't just a visited-set with extra steps โ a set can only answer "have I seen this," but you need the actual cloned object back to wire into
.neighbors, so the dict does both jobs at once - Registering a clone before recursing into its neighbors is the key step โ this is an undirected graph, so a neighbor can point straight back to a node still mid-clone, and that's an infinite recursion without the early registration
- Disconnected Clone Graph follow-up: the output should be sized by component count, not by how many input nodes you were handed โ one entry point per component is enough, since the rest is reachable through
.neighbors - Word Ladder is grid BFS's snapshot-queue trick again, just with neighbors generated on the fly (try all 26 letters at every position) instead of read off a fixed adjacency list
- Bidirectional BFS's real optimization is the swap: always expand whichever side (front or back) is smaller, or the whole benefit of searching from both ends disappears
- Word Ladder II needs a whole BFS level removed from the word set at once, not word-by-word โ otherwise the second word in the same level that could reach the same next word sees it as already gone and silently loses a valid parent
- Bug pattern of the day: reusing a variable name for a loop when the original value is still needed later โ
nodegot overwritten in the middle of a BFS,wordgot shadowed inside a recursive backtrack function, and areturn []was placed one indent level too shallow, so it ran after only the first batch instead of after the whole queue was empty. Different variable names, same lesson as last time