What they test: recursion/stack discipline, visited invariants, cycle detection, and "explore then backtrack" reasoning.
What you should say out loud:
- "DFS explores one branch fully before trying the next."
- "Invariant: visited prevents infinite loops."
- "For cycle detection in directed graphs, track recursion stack (colors)."
Depth-First Search traverses a graph by going as deep as possible before backtracking. DFS underpins cycle detection, topological sort (DFS postorder), SCC algorithms, and backtracking.
- Graph traversal / reachability
- Cycle detection (directed with recursion stack)
- Enumerating all paths (on DAG / with constraints)
- Backtracking-style search
- Visited invariant: each node is processed once (for traversal).
- Stack invariant (directed cycle): a back-edge to a node "in stack" implies a cycle.
- Path invariant (all-paths): current path reflects recursion stack and is restored on return.
Following edges recursively explores the entire reachable subgraph; backtracking restores state enabling exploration of alternate branches.
- "Return DFS traversal order from node s."
- "Detect if directed graph has a cycle."
- "Return all paths from s to t (typically DAG)."
- Time: O(V + E) for traversal/cycle detection
- Space: O(V) for visited + recursion/explicit stack
- All-paths can be exponential in number of paths.
- Prefer iterative DFS if recursion depth might be large.
- If you implement both, ensure they match by enforcing deterministic neighbor order.
- For cycle detection: use 3-color (0=unvisited,1=visiting,2=done) or recursion-stack set.
- Stack overflow on deep graphs (recursive DFS).
- Mistaking undirected vs directed cycle detection logic.
- For all-paths: forgetting to copy the current path before storing.
- Number of Islands (LC #200) (grid DFS)
- Course Schedule (LC #207) (cycle detection)
- All Paths From Source to Target (LC #797)
- Word Search (LC #79)
- Preorder/postorder DFS
- DFS timestamps (discovery/finish)
- Tarjan/Kosaraju SCC
- DFS for topological sorting
package dfs
type Graph struct {
// your representation
}
func NewGraph() *Graph
func (g *Graph) AddEdge(u, v int)
func DFSRecursive(g *Graph, start int) []int
func DFSIterative(g *Graph, start int) []int
// HasCycle detects a cycle in a directed graph.
func HasCycle(g *Graph) bool
// FindAllPaths returns all simple paths from start to target.
// If you allow cycles, define how you prevent infinite paths (usually disallow revisiting nodes in current path).
func FindAllPaths(g *Graph, start, target int) [][]int