DFS Depth First Search on Graph in DSA Go - Time & Space Complexity
We want to understand how the time needed to explore a graph grows as the graph gets bigger using Depth First Search (DFS).
How does the number of steps change when the graph has more nodes and edges?
Analyze the time complexity of the following code snippet.
func DFS(graph map[int][]int, start int, visited map[int]bool) {
visited[start] = true
for _, neighbor := range graph[start] {
if !visited[neighbor] {
DFS(graph, neighbor, visited)
}
}
}
This code visits all nodes reachable from the start node by exploring as far as possible along each branch before backtracking.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each node and exploring its neighbors recursively.
- How many times: Each node is visited once, and each edge is checked once during the traversal.
As the graph grows, the DFS visits every node and edge once, so the work grows with the total nodes and edges.
| Input Size (n nodes, m edges) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 25 visits (10 nodes + 15 edges) |
| 100 nodes, 200 edges | About 300 visits (100 nodes + 200 edges) |
| 1000 nodes, 3000 edges | About 4000 visits (1000 nodes + 3000 edges) |
Pattern observation: The total steps increase roughly by the sum of nodes and edges as the graph grows.
Time Complexity: O(n + m)
This means the time to finish DFS grows linearly with the number of nodes plus the number of edges in the graph.
[X] Wrong: "DFS always takes O(n²) time because it uses recursion and loops."
[OK] Correct: DFS visits each node and edge only once, so it does not repeat work unnecessarily. The time depends on the actual graph size, not just the number of nodes squared.
Understanding DFS time complexity helps you explain how graph algorithms scale, a key skill in many coding challenges and real-world problems.
"What if the graph is represented as an adjacency matrix instead of adjacency lists? How would the time complexity change?"
Practice
Solution
Step 1: Understand DFS traversal
DFS explores a graph by going deep into one branch before backtracking to explore others.Step 2: Compare options with DFS behavior
Explore as far as possible along each branch before backtracking matches this behavior exactly, while others describe BFS or incorrect methods.Final Answer:
Explore as far as possible along each branch before backtracking -> Option CQuick Check:
DFS = deep exploration first [OK]
- Confusing DFS with BFS
- Thinking DFS visits neighbors first
- Assuming DFS visits nodes by distance
graph map[int][]int?Solution
Step 1: Identify correct visited type for DFS
Visited should be a map[int]bool to mark nodes visited or not.Step 2: Check options for visited parameter type
Only func dfs(node int, visited map[int]bool) {} uses map[int]bool, others use incorrect types.Final Answer:
func dfs(node int, visited map[int]bool) {} -> Option AQuick Check:
Visited map with bool = correct DFS parameter [OK]
- Using slice instead of map for visited
- Using wrong map value type
- Ignoring visited parameter
graph := map[int][]int{
1: {2, 3},
2: {4},
3: {},
4: {},
}
visited := map[int]bool{}
var result []int
var dfs func(int)
dfs = func(node int) {
if visited[node] {
return
}
visited[node] = true
result = append(result, node)
for _, n := range graph[node] {
dfs(n)
}
}
dfs(1)
fmt.Println(result)Solution
Step 1: Trace DFS starting at node 1
Visit 1, then go to 2, then 4 (no children), backtrack, then visit 3.Step 2: Record order of visited nodes
Order is 1, 2, 4, 3 as DFS explores deep before backtracking.Final Answer:
[1 2 4 3] -> Option AQuick Check:
DFS order = [1 2 4 3] [OK]
- Visiting neighbors in wrong order
- Confusing BFS order with DFS
- Not marking visited nodes
func dfs(node int, graph map[int][]int, visited map[int]bool) {
if visited[node] {
return
}
visited[node] = true
for _, n := range graph[node] {
dfs(n, graph, visited)
}
}
// Called as dfs(1, graph, visited)Solution
Step 1: Analyze DFS function behavior
Function marks visited and recurses but does not process or print nodes.Step 2: Identify missing action
DFS usually processes nodes (e.g., print or collect), missing here causes no visible output.Final Answer:
No code to process or print the node -> Option DQuick Check:
DFS missing node processing step [OK]
- Assuming marking visited is enough
- Forgetting to print or collect nodes
- Thinking recursion stops without base case
Solution
Step 1: Understand cycle detection in DFS
Detect cycles by tracking nodes currently in recursion stack to find back edges.Step 2: Choose correct method
Using a recursion stack map helps detect if a node is revisited while still in the current path.Final Answer:
Use a recursion stack map to track nodes currently in the call stack -> Option BQuick Check:
Cycle detection = recursion stack tracking [OK]
- Marking visited too late
- Using BFS which doesn't detect cycles easily
- Ignoring visited nodes causing infinite loops
Ready to prove it?
Pass the test and this pattern moves unknown
