Bird
Raised Fist0
DSA Rustprogramming~20 mins

Topological Sort Using Kahn's Algorithm BFS in DSA Rust - Practice Problems & Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Kahn's Algorithm Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of Kahn's Algorithm on a Simple DAG
What is the output of the following Rust code implementing Kahn's Algorithm for topological sorting on the given graph?
DSA Rust
use std::collections::{VecDeque, HashMap};

fn kahn_topological_sort(graph: &HashMap<char, Vec<char>>) -> Vec<char> {
    let mut in_degree = HashMap::new();
    for &node in graph.keys() {
        in_degree.insert(node, 0);
    }
    for edges in graph.values() {
        for &v in edges {
            *in_degree.entry(v).or_insert(0) += 1;
        }
    }

    let mut queue = VecDeque::new();
    for (&node, &deg) in &in_degree {
        if deg == 0 {
            queue.push_back(node);
        }
    }

    let mut topo_order = Vec::new();
    while let Some(u) = queue.pop_front() {
        topo_order.push(u);
        if let Some(neighbors) = graph.get(&u) {
            for &v in neighbors {
                let deg = in_degree.get_mut(&v).unwrap();
                *deg -= 1;
                if *deg == 0 {
                    queue.push_back(v);
                }
            }
        }
    }

    topo_order
}

fn main() {
    let mut graph = HashMap::new();
    graph.insert('A', vec!['C']);
    graph.insert('B', vec!['C', 'D']);
    graph.insert('C', vec!['E']);
    graph.insert('D', vec!['F']);
    graph.insert('E', vec!['H', 'F']);
    graph.insert('F', vec!['G']);
    graph.insert('G', vec![]);
    graph.insert('H', vec![]);

    let result = kahn_topological_sort(&graph);
    println!("{:?}", result);
}
A["B", "A", "C", "D", "E", "H", "F", "G"]
B["B", "A", "D", "C", "E", "F", "H", "G"]
C["A", "B", "D", "C", "E", "F", "G", "H"]
D["A", "B", "C", "D", "E", "H", "F", "G"]
Attempts:
2 left
💡 Hint
Remember that nodes with zero incoming edges are processed first, and neighbors' in-degree is decreased accordingly.
🧠 Conceptual
intermediate
1:30remaining
Detecting Cycles with Kahn's Algorithm
What does it mean if Kahn's Algorithm finishes and the topological order contains fewer nodes than the graph?
AThe graph contains a cycle, so a full topological order is impossible.
BThe graph is disconnected, so some nodes are unreachable.
CThe graph is empty, so no nodes exist to process.
DThe algorithm terminated early due to a runtime error.
Attempts:
2 left
💡 Hint
Think about what prevents nodes from having zero in-degree.
🔧 Debug
advanced
2:00remaining
Identify the Bug in Kahn's Algorithm Implementation
Given this Rust code snippet for Kahn's Algorithm, what is the bug causing incorrect topological order?
DSA Rust
use std::collections::{VecDeque, HashMap};

fn kahn_sort_bug(graph: &HashMap<char, Vec<char>>) -> Vec<char> {
    let mut in_degree = HashMap::new();
    for &node in graph.keys() {
        in_degree.insert(node, 0);
    }
    for edges in graph.values() {
        for &v in edges {
            *in_degree.entry(v).or_insert(0) += 1;
        }
    }

    let mut queue = VecDeque::new();
    for (&node, &deg) in &in_degree {
        if deg > 0 {
            queue.push_back(node);
        }
    }

    let mut topo_order = Vec::new();
    while let Some(u) = queue.pop_front() {
        topo_order.push(u);
        if let Some(neighbors) = graph.get(&u) {
            for &v in neighbors {
                let deg = in_degree.get_mut(&v).unwrap();
                *deg -= 1;
                if *deg == 0 {
                    queue.push_back(v);
                }
            }
        }
    }

    topo_order
}
AThe initial queue includes nodes with in-degree > 0 instead of 0.
BThe in-degree is not calculated correctly for all nodes.
CNeighbors are not processed to reduce their in-degree.
DThe topo_order vector is not returned at the end.
Attempts:
2 left
💡 Hint
Check the condition used to add nodes to the initial queue.
🚀 Application
advanced
1:30remaining
Number of Possible Topological Orders
Given a DAG with nodes A, B, C where A points to C and B points to C, how many different valid topological orders exist?
A1
B3
C2
D6
Attempts:
2 left
💡 Hint
Consider the order constraints and which nodes can be swapped.
❓ Predict Output
expert
2:00remaining
Output of Kahn's Algorithm on a Graph with Cycle
What is the output of the following Rust code implementing Kahn's Algorithm on a graph containing a cycle?
DSA Rust
use std::collections::{VecDeque, HashMap};

fn kahn_topological_sort(graph: &HashMap<char, Vec<char>>) -> Vec<char> {
    let mut in_degree = HashMap::new();
    for &node in graph.keys() {
        in_degree.insert(node, 0);
    }
    for edges in graph.values() {
        for &v in edges {
            *in_degree.entry(v).or_insert(0) += 1;
        }
    }

    let mut queue = VecDeque::new();
    for (&node, &deg) in &in_degree {
        if deg == 0 {
            queue.push_back(node);
        }
    }

    let mut topo_order = Vec::new();
    while let Some(u) = queue.pop_front() {
        topo_order.push(u);
        if let Some(neighbors) = graph.get(&u) {
            for &v in neighbors {
                let deg = in_degree.get_mut(&v).unwrap();
                *deg -= 1;
                if *deg == 0 {
                    queue.push_back(v);
                }
            }
        }
    }

    topo_order
}

fn main() {
    let mut graph = HashMap::new();
    graph.insert('A', vec!['B']);
    graph.insert('B', vec!['C']);
    graph.insert('C', vec!['A']); // cycle A->B->C->A

    let result = kahn_topological_sort(&graph);
    println!("{:?}", result);
}
A["B", "C"]
B[]
C["A"]
D["A", "B", "C"]
Attempts:
2 left
💡 Hint
If a cycle exists, no node will have zero in-degree to start the process.

Practice

(1/5)
1. What is the main purpose of Kahn's Algorithm in graph theory?
easy
A. To find a topological ordering of a Directed Acyclic Graph (DAG)
B. To find the shortest path between two nodes
C. To detect cycles in an undirected graph
D. To calculate the minimum spanning tree

Solution

  1. Step 1: Understand Kahn's Algorithm goal

    Kahn's Algorithm is designed to produce a linear ordering of vertices in a Directed Acyclic Graph (DAG) such that for every directed edge uv, vertex u comes before v in the ordering.
  2. Step 2: Compare with other graph algorithms

    Shortest path algorithms find paths, cycle detection checks for loops, and minimum spanning tree algorithms work on undirected graphs. Kahn's Algorithm specifically produces a topological order.
  3. Final Answer:

    To find a topological ordering of a Directed Acyclic Graph (DAG) -> Option A
  4. Quick Check:

    Topological sort = Kahn's Algorithm purpose [OK]
Hint: Kahn's Algorithm always orders DAG nodes topologically [OK]
Common Mistakes:
  • Confusing topological sort with shortest path
  • Thinking it detects cycles in undirected graphs
  • Mixing it with minimum spanning tree algorithms
2. Which Rust data structure is best suited to keep track of nodes with zero incoming edges in Kahn's Algorithm?
easy
A. HashMap
B. VecDeque (double-ended queue)
C. BinaryHeap
D. LinkedList

Solution

  1. Step 1: Identify the need for queue behavior

    Kahn's Algorithm processes nodes with zero incoming edges in FIFO order, so a queue is needed to efficiently pop from front and push at back.
  2. Step 2: Choose the Rust data structure

    VecDeque provides efficient push and pop operations at both ends, making it ideal for queue operations. HashMap is for key-value storage, BinaryHeap is a priority queue, and LinkedList is less efficient in Rust.
  3. Final Answer:

    VecDeque (double-ended queue) -> Option B
  4. Quick Check:

    Queue for zero in-degree nodes = VecDeque [OK]
Hint: Use VecDeque for queue operations in Rust [OK]
Common Mistakes:
  • Using HashMap instead of a queue
  • Choosing BinaryHeap which is a priority queue
  • Using LinkedList which is inefficient in Rust
3. Given the following Rust code snippet implementing Kahn's Algorithm, what will be the printed topological order?
let edges = vec![(0, 1), (0, 2), (1, 3), (2, 3)];
let n = 4;
// Assume graph and in_degree are built correctly
// After running Kahn's Algorithm, the order vector is printed
println!("{:?}", order);
medium
A. [0, 1, 2, 3]
B. [3, 1, 2, 0]
C. [0, 2, 1, 3]
D. [1, 0, 2, 3]

Solution

  1. Step 1: Analyze the graph edges and in-degree

    Edges: 0->1, 0->2, 1->3, 2->3. Node 0 has in-degree 0, nodes 1 and 2 have in-degree 1, node 3 has in-degree 2.
  2. Step 2: Perform Kahn's Algorithm BFS

    Start with node 0 (in-degree 0). Remove it, reduce in-degree of 1 and 2 to 0. Add 1 and 2 to queue. Next, remove 1, then 2, then 3. Order is [0, 1, 2, 3]. However, since nodes 1 and 2 become zero in-degree simultaneously, the order of processing them can vary. If we process 2 before 1, the order is [0, 2, 1, 3], which is also valid.
  3. Final Answer:

    [0, 2, 1, 3] -> Option C
  4. Quick Check:

    Topological order respects edges = [0, 2, 1, 3] [OK]
Hint: Start with zero in-degree nodes and process neighbors [OK]
Common Mistakes:
  • Reversing order of nodes processed
  • Ignoring in-degree updates
  • Assuming multiple valid orders without checking edges
4. Identify the bug in this Rust snippet of Kahn's Algorithm:
for &node in &graph[node] {
    in_degree[node] -= 1;
    if in_degree[node] == 0 {
        queue.push_back(node);
    }
}
medium
A. Missing initialization of in_degree array
B. Should use 'queue.push_front' instead of 'push_back'
C. Queue should be a stack for correct order
D. Using 'node' as loop variable shadows outer 'node', causing wrong indexing

Solution

  1. Step 1: Understand variable shadowing in the loop

    The loop uses 'node' as the loop variable, which shadows the outer 'node' variable used to index graph. This causes confusion and incorrect indexing.
  2. Step 2: Correct the variable naming

    Use a different variable name like 'neighbor' in the loop to avoid shadowing and correctly access neighbors.
  3. Final Answer:

    Using 'node' as loop variable shadows outer 'node', causing wrong indexing -> Option D
  4. Quick Check:

    Variable shadowing causes bugs = Using 'node' as loop variable shadows outer 'node', causing wrong indexing [OK]
Hint: Avoid reusing variable names in nested loops [OK]
Common Mistakes:
  • Ignoring variable shadowing
  • Confusing queue with stack usage
  • Assuming in_degree initialization is the bug
5. You have a graph with edges: [(5, 2), (5, 0), (4, 0), (4, 1), (2, 3), (3, 1)]. Using Kahn's Algorithm, which of the following is a valid topological order?
hard
A. [5, 4, 2, 3, 1, 0]
B. [0, 1, 2, 3, 4, 5]
C. [5, 2, 4, 3, 1, 0]
D. [1, 3, 2, 4, 5, 0]

Solution

  1. Step 1: Calculate in-degree for each node

    Nodes: 0,1,2,3,4,5 In-degree: 0(2), 1(2), 2(1), 3(1), 4(0), 5(0)
  2. Step 2: Perform Kahn's Algorithm steps

    Start with nodes 4 and 5 (in-degree 0). Remove 5: reduce in-degree of 2 and 0. Remove 4: reduce in-degree of 0 and 1. Then remove 2, 3, 1, 0 in order. One valid order is [5, 4, 2, 3, 1, 0].
  3. Final Answer:

    [5, 4, 2, 3, 1, 0] -> Option A
  4. Quick Check:

    Valid topological order respects edges = [5, 4, 2, 3, 1, 0] [OK]
Hint: Start with zero in-degree nodes and remove edges stepwise [OK]
Common Mistakes:
  • Choosing orders that violate edge directions
  • Ignoring initial zero in-degree nodes
  • Mixing node order without updating in-degree
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