Bird
Raised Fist0
DSA Rustprogramming~20 mins

DFS Depth First Search on Graph in DSA Rust - Practice Problems & Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
DFS Mastery Badge
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of DFS traversal on a simple graph

What is the output of the DFS traversal starting from node 0?

DSA Rust
use std::collections::HashMap;

fn dfs(graph: &HashMap<i32, Vec<i32>>, start: i32, visited: &mut Vec<i32>, result: &mut Vec<i32>) {
    if visited.contains(&start) {
        return;
    }
    visited.push(start);
    result.push(start);
    if let Some(neighbors) = graph.get(&start) {
        for &node in neighbors {
            dfs(graph, node, visited, result);
        }
    }
}

fn main() {
    let mut graph = HashMap::new();
    graph.insert(0, vec![1, 2]);
    graph.insert(1, vec![3]);
    graph.insert(2, vec![3]);
    graph.insert(3, vec![]);

    let mut visited = Vec::new();
    let mut result = Vec::new();
    dfs(&graph, 0, &mut visited, &mut result);
    println!("{:?}", result);
}
A[0, 1, 3, 2]
B[0, 3, 1, 2]
C[0, 1, 2, 3]
D[0, 2, 3, 1]
Attempts:
2 left
💡 Hint

DFS explores as far as possible along each branch before backtracking.

🧠 Conceptual
intermediate
1:30remaining
Understanding DFS visited nodes tracking

Why is it important to track visited nodes in DFS on a graph?

ATo count the total number of edges in the graph.
BTo ensure nodes are visited in numerical order.
CTo avoid revisiting nodes and prevent infinite loops in cyclic graphs.
DTo sort the nodes before traversal.
Attempts:
2 left
💡 Hint

Think about what happens if the graph has cycles.

❓ Predict Output
advanced
2:00remaining
DFS output on disconnected graph

What is the output of DFS starting from node 0 on this disconnected graph?

DSA Rust
use std::collections::HashMap;

fn dfs(graph: &HashMap<i32, Vec<i32>>, start: i32, visited: &mut Vec<i32>, result: &mut Vec<i32>) {
    if visited.contains(&start) {
        return;
    }
    visited.push(start);
    result.push(start);
    if let Some(neighbors) = graph.get(&start) {
        for &node in neighbors {
            dfs(graph, node, visited, result);
        }
    }
}

fn main() {
    let mut graph = HashMap::new();
    graph.insert(0, vec![1]);
    graph.insert(1, vec![]);
    graph.insert(2, vec![3]);
    graph.insert(3, vec![]);

    let mut visited = Vec::new();
    let mut result = Vec::new();
    dfs(&graph, 0, &mut visited, &mut result);
    println!("{:?}", result);
}
A[0, 1]
B[1, 0]
C[2, 3]
D[0, 1, 2, 3]
Attempts:
2 left
💡 Hint

DFS only visits nodes reachable from the start node.

🔧 Debug
advanced
2:00remaining
Identify the error in DFS implementation

What error will this DFS code produce when run?

DSA Rust
use std::collections::HashMap;

fn dfs(graph: &HashMap<i32, Vec<i32>>, start: i32, visited: &mut Vec<i32>, result: &mut Vec<i32>) {
    if visited.contains(&start) {
        return;
    }
    visited.push(start);
    result.push(start);
    for node in graph.get(&start).unwrap() {
        dfs(graph, *node, visited, result);
    }
}

fn main() {
    let mut graph = HashMap::new();
    graph.insert(0, vec![1]);
    graph.insert(1, vec![2]);
    // Node 2 is missing from graph keys

    let mut visited = Vec::new();
    let mut result = Vec::new();
    dfs(&graph, 0, &mut visited, &mut result);
    println!("{:?}", result);
}
A[0, 1, 2]
BStack overflow due to infinite recursion
CCompilation error: missing semicolon
Dpanic at 'called `Option::unwrap()` on a `None` value'
Attempts:
2 left
💡 Hint

Check what happens when a node is not present in the graph keys.

🚀 Application
expert
2:30remaining
Number of connected components using DFS

Given an undirected graph represented as adjacency list, what is the number of connected components?

Graph edges: 0-1, 1-2, 3-4

DSA Rust
use std::collections::{HashMap, HashSet};

fn dfs(node: i32, graph: &HashMap<i32, Vec<i32>>, visited: &mut HashSet<i32>) {
    if visited.contains(&node) {
        return;
    }
    visited.insert(node);
    if let Some(neighbors) = graph.get(&node) {
        for &neighbor in neighbors {
            dfs(neighbor, graph, visited);
        }
    }
}

fn main() {
    let mut graph = HashMap::new();
    graph.insert(0, vec![1]);
    graph.insert(1, vec![0, 2]);
    graph.insert(2, vec![1]);
    graph.insert(3, vec![4]);
    graph.insert(4, vec![3]);

    let mut visited = HashSet::new();
    let mut count = 0;
    for &node in graph.keys() {
        if !visited.contains(&node) {
            dfs(node, &graph, &mut visited);
            count += 1;
        }
    }
    println!("{}", count);
}
A1
B2
C3
D4
Attempts:
2 left
💡 Hint

Count how many times DFS starts on an unvisited node.

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