Bird
Raised Fist0
DSA Rustprogramming~5 mins

DFS Depth First Search on Graph in DSA Rust - Time & Space Complexity

Choose your learning style10 modes available
Time Complexity: DFS Depth First Search on Graph
O(n + e)
Understanding Time Complexity

We want to understand how the time taken by Depth First Search (DFS) grows as the graph size increases.

Specifically, how does DFS's work change when the graph has more nodes and edges?

Scenario Under Consideration

Analyze the time complexity of the following code snippet.

fn dfs(graph: &Vec<Vec<usize>>, node: usize, visited: &mut Vec<bool>) {
    visited[node] = true;
    for &neighbor in &graph[node] {
        if !visited[neighbor] {
            dfs(graph, neighbor, visited);
        }
    }
}

This code visits all nodes reachable from a starting node using DFS on an adjacency list graph.

Identify Repeating Operations

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.
How Execution Grows With Input

As the number of nodes (n) and edges (e) grow, DFS visits all nodes and edges once.

Input Size (n, e)Approx. Operations
10 nodes, 15 edgesAbout 10 node visits + 15 edge checks = 25 operations
100 nodes, 200 edgesAbout 100 + 200 = 300 operations
1000 nodes, 5000 edgesAbout 1000 + 5000 = 6000 operations

Pattern observation: Operations grow roughly in proportion to nodes plus edges.

Final Time Complexity

Time Complexity: O(n + e)

This means DFS takes time proportional to the number of nodes plus edges in the graph.

Common Mistake

[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 its time depends on the graph size, not the square of nodes.

Interview Connect

Understanding DFS time complexity helps you explain how graph traversal scales, a key skill in many coding challenges.

Self-Check

"What if the graph was represented as an adjacency matrix instead of a list? How would the time complexity change?"

Practice

(1/5)
1. What is the main idea behind Depth First Search (DFS) on a graph?
easy
A. Explore as far as possible along each branch before backtracking
B. Visit all nodes at the current depth before moving deeper
C. Visit nodes randomly without any order
D. Only visit nodes with the highest value first

Solution

  1. Step 1: Understand DFS traversal

    DFS explores a graph by going deep into one branch before exploring others.
  2. Step 2: Compare with other traversal methods

    BFS visits nodes level by level, but DFS goes deep first.
  3. Final Answer:

    Explore as far as possible along each branch before backtracking -> Option A
  4. Quick Check:

    DFS = deep exploration first [OK]
Hint: DFS means go deep first, then backtrack [OK]
Common Mistakes:
  • Confusing DFS with BFS
  • Thinking DFS visits nodes level-wise
  • Assuming DFS visits nodes randomly
2. Which of the following is the correct Rust function signature for a recursive DFS function on a graph represented as adjacency list?
easy
A. fn dfs(graph: &mut Vec, node: usize, visited: Vec<bool>)
B. fn dfs(graph: Vec, node: usize, visited: Vec<bool>)
C. fn dfs(graph: &Vec, node: usize, visited: &mut Vec<bool>)
D. fn dfs(graph: Vec, node: usize, visited: &mut Vec<bool>)

Solution

  1. Step 1: Understand parameter passing in Rust for DFS

    The graph should be passed by reference to avoid copying, and visited vector should be mutable reference to mark nodes visited.
  2. Step 2: Check each option

    fn dfs(graph: &Vec, node: usize, visited: &mut Vec<bool>) passes graph by reference and visited as mutable reference, which is correct for DFS recursion.
  3. Final Answer:

    fn dfs(graph: &Vec, node: usize, visited: &mut Vec<bool>) -> Option C
  4. Quick Check:

    Graph by ref + visited mutable ref = correct DFS signature [OK]
Hint: Pass graph by ref and visited as mutable ref [OK]
Common Mistakes:
  • Passing graph or visited by value causing copies
  • Not using mutable reference for visited
  • Using mutable reference for graph unnecessarily
3. What is the output of the following Rust DFS traversal starting from node 0?
fn dfs(graph: &Vec, node: usize, visited: &mut Vec<bool>, result: &mut Vec<usize>) {
    visited[node] = true;
    result.push(node);
    for &neighbor in &graph[node] {
        if !visited[neighbor] {
            dfs(graph, neighbor, visited, result);
        }
    }
}

fn main() {
    let graph = vec![
        vec![1, 2],
        vec![0, 3],
        vec![0],
        vec![1]
    ];
    let mut visited = vec![false; 4];
    let mut result = Vec::new();
    dfs(&graph, 0, &mut visited, &mut result);
    println!("{:?}", result);
}
medium
A. [0, 2, 1, 3]
B. [0, 1, 3, 2]
C. [0, 1, 2, 3]
D. [1, 0, 2, 3]

Solution

  1. Step 1: Trace DFS starting at node 0

    Start at 0, mark visited, add 0. Neighbors: 1, 2. Visit 1 first.
  2. Step 2: Continue DFS from node 1

    Visit 1, add 1. Neighbors: 0 (visited), 3 (not visited). Visit 3 next.
  3. Step 3: Visit node 3

    Visit 3, add 3. Neighbor: 1 (visited). Backtrack to 0 and visit 2.
  4. Step 4: Visit node 2

    Visit 2, add 2. Neighbor: 0 (visited). DFS complete.
  5. Final Answer:

    [0, 1, 3, 2] -> Option B
  6. Quick Check:

    DFS order from 0 = [0,1,3,2] [OK]
Hint: Follow neighbors in order, mark visited, backtrack [OK]
Common Mistakes:
  • Visiting neighbors out of order
  • Not marking visited nodes
  • Confusing BFS order with DFS
4. Identify the bug in this DFS Rust code snippet and choose the fix:
fn dfs(graph: &Vec, node: usize, visited: &mut Vec<bool>) {
    visited[node] = true;
    for neighbor in &graph[node] {
        if visited[*neighbor] {
            dfs(graph, *neighbor, visited);
        }
    }
}
medium
A. Change if visited[*neighbor] to if !visited[*neighbor]
B. Change visited[node] = true to visited[node] = false
C. Remove the for loop and call dfs only once
D. Change neighbor to node inside the loop

Solution

  1. Step 1: Analyze the condition for recursive DFS call

    The code calls dfs only if visited[*neighbor] is true, meaning already visited nodes are revisited, causing infinite recursion.
  2. Step 2: Correct the condition to avoid revisiting

    Change condition to if !visited[*neighbor] to visit only unvisited neighbors.
  3. Final Answer:

    Change if visited[*neighbor] to if !visited[*neighbor] -> Option A
  4. Quick Check:

    Visit unvisited neighbors only [OK]
Hint: Call DFS only on unvisited neighbors [OK]
Common Mistakes:
  • Calling DFS on visited nodes causing infinite loops
  • Incorrectly marking nodes as unvisited
  • Removing necessary loops
5. Given a graph with possible cycles, how can you modify DFS in Rust to detect if the graph contains a cycle?
hard
A. Use BFS instead of DFS to detect cycles
B. Only mark nodes visited after all neighbors are visited
C. Ignore visited nodes and continue traversal
D. Use a recursion stack (call stack) boolean vector to track nodes in the current path and detect back edges

Solution

  1. Step 1: Understand cycle detection in DFS

    To detect cycles, track nodes currently in recursion stack to find back edges indicating cycles.
  2. Step 2: Implement recursion stack tracking

    Use a boolean vector to mark nodes in current DFS path; if a neighbor is in this stack, a cycle exists.
  3. Step 3: Other options are incorrect

    Marking visited after neighbors or using BFS won't detect cycles reliably; ignoring visited nodes causes infinite loops.
  4. Final Answer:

    Use a recursion stack (call stack) boolean vector to track nodes in the current path and detect back edges -> Option D
  5. Quick Check:

    Recursion stack tracks cycles in DFS [OK]
Hint: Track recursion stack to find cycles in DFS [OK]
Common Mistakes:
  • Not tracking recursion stack causing missed cycles
  • Using BFS which needs extra logic for cycles
  • Ignoring visited nodes causing infinite loops
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard