DFS Depth First Search on Graph in DSA Java - Time & Space Complexity
We want to understand how the time needed to explore a graph using DFS changes as the graph grows.
Specifically, how does the number of steps grow when the graph has more nodes and edges?
Analyze the time complexity of the following code snippet.
void dfs(int node, boolean[] visited, List<List<Integer>> graph) {
visited[node] = true;
for (int neighbor : graph.get(node)) {
if (!visited[neighbor]) {
dfs(neighbor, visited, graph);
}
}
}
This code visits all nodes reachable from the starting node using depth-first search on an adjacency list graph.
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.
As the graph grows, DFS visits every node and edge once, so the work grows with both.
| Input Size (n nodes, m edges) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 10 + 15 = 25 operations |
| 100 nodes, 200 edges | About 100 + 200 = 300 operations |
| 1000 nodes, 5000 edges | About 1000 + 5000 = 6000 operations |
Pattern observation: The total steps grow roughly in proportion to the number of nodes plus edges.
Time Complexity: O(n + m)
This means the time to run DFS grows linearly with the total number of nodes and edges in the graph.
[X] Wrong: "DFS takes O(n²) time because it uses recursion inside a loop."
[OK] Correct: Each node and edge is visited only once, so the total work is linear, not quadratic.
Understanding DFS time complexity helps you explain how graph traversal scales and why it is efficient for many problems.
"What if the graph was represented by 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 other branches.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 DQuick Check:
DFS = deep exploration first [OK]
- Confusing DFS with BFS
- Thinking DFS visits neighbors first
- Assuming DFS visits nodes by distance
Solution
Step 1: Identify typical DFS method signature
Common DFS signature is dfs(currentNode, visitedArray, graph).Step 2: Match options to this signature
dfs(0, visited, graph); matches the order: node, visited, graph. Others have wrong parameter order.Final Answer:
dfs(0, visited, graph); -> Option AQuick Check:
Correct parameter order = dfs(node, visited, graph) [OK]
- Mixing parameter order
- Using uppercase method name 'DFS'
- Passing graph before node
graph = {{1, 2}, {0, 3}, {0}, {1}} and starting DFS from node 0, what is the order of nodes visited?Solution
Step 1: Start DFS at node 0 and visit neighbors
From 0, neighbors are 1 and 2. DFS visits 1 first (assuming adjacency order).Step 2: From node 1, visit its neighbors
Neighbors of 1 are 0 (visited) and 3. Visit 3 next.Step 3: Backtrack and visit remaining neighbors
After 3, backtrack to 0 and visit 2.Final Answer:
[0, 1, 3, 2] -> Option AQuick Check:
DFS order = 0,1,3,2 [OK]
- Visiting neighbors in wrong order
- Not backtracking correctly
- Confusing BFS order with DFS
void dfs(int node, boolean[] visited, List<Integer>[] graph) {
visited[node] = true;
for (int neighbor : graph[node]) {
if (visited[neighbor]) {
dfs(neighbor, visited, graph);
}
}
}Solution
Step 1: Check visited condition before recursive call
The code calls dfs(neighbor) only if visited[neighbor] is true, which means already visited.Step 2: Identify the problem caused
This causes infinite recursion because it revisits nodes already visited instead of skipping them.Final Answer:
It calls dfs on already visited neighbors causing infinite recursion -> Option BQuick Check:
Call dfs only if neighbor not visited [OK]
- Calling dfs on visited nodes
- Forgetting to mark visited nodes
- Incorrect loop over neighbors
graph = {{1, 2}, {0, 3}, {0, 4}, {1}, {2}}Which DFS approach correctly determines if node 4 is reachable from node 0?
Solution
Step 1: Understand the goal
We want to check if node 4 is reachable from node 0, so start DFS at 0.Step 2: Use DFS to find target node
During DFS, if node 4 is found, stop and return true immediately.Step 3: Evaluate options
Run DFS from 0, stop and return true if node 4 is found during traversal matches this approach. Run DFS from 4, stop and return true if node 0 is found during traversal starts from wrong node. Run DFS from 0 and count all visited nodes without checking for 4 ignores target. Run DFS from 0 but skip node 2 to avoid cycles skips nodes incorrectly.Final Answer:
Run DFS from 0, stop and return true if node 4 is found during traversal -> Option CQuick Check:
DFS from start, stop on target found [OK]
- Starting DFS from wrong node
- Not checking for target during traversal
- Skipping nodes that are part of path
Ready to prove it?
Pass the test and this pattern moves unknown
