Topological Sort Using Kahn's Algorithm BFS in DSA Java - Time & Space Complexity
We want to understand how the time needed to perform topological sort using Kahn's Algorithm grows as the graph size increases.
Specifically, how the number of nodes and edges affects the work done.
Analyze the time complexity of the following code snippet.
public List<Integer> kahnTopologicalSort(int V, List<List<Integer>> adj) {
int[] indegree = new int[V];
for (int i = 0; i < V; i++) {
for (int node : adj.get(i)) {
indegree[node]++;
}
}
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < V; i++) {
if (indegree[i] == 0) q.add(i);
}
List<Integer> topo = new ArrayList<>();
while (!q.isEmpty()) {
int u = q.poll();
topo.add(u);
for (int v : adj.get(u)) {
indegree[v]--;
if (indegree[v] == 0) q.add(v);
}
}
return topo;
}
This code performs a topological sort on a directed graph using Kahn's BFS algorithm.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Traversing all edges and nodes in the graph.
- How many times: Each edge is visited once when counting indegrees and once when processing nodes from the queue.
The work grows with the number of nodes and edges. For example:
| Input Size (V = nodes, E = edges) | Approx. Operations |
|---|---|
| V=10, E=15 | About 25 operations (counting edges and nodes) |
| V=100, E=200 | About 300 operations |
| V=1000, E=5000 | About 6000 operations |
Pattern observation: The operations grow roughly proportional to the sum of nodes and edges.
Time Complexity: O(V + E)
This means the time needed grows linearly with the total number of nodes plus edges in the graph.
[X] Wrong: "The algorithm takes O(V²) time because of nested loops."
[OK] Correct: The inner loops do not run V times for each node; they run once per edge overall, so total work is proportional to edges, not nodes squared.
Understanding this time complexity helps you explain why Kahn's Algorithm is efficient for scheduling and dependency problems in real projects.
"What if the graph was represented using an adjacency matrix instead of adjacency lists? How would the time complexity change?"
Practice
Solution
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 u -> v, u comes before v in the ordering.Step 2: Compare with other graph algorithms
Other options describe different algorithms: cycle detection, shortest path, and minimum spanning tree are unrelated to Kahn's Algorithm.Final Answer:
To find a topological ordering of a Directed Acyclic Graph (DAG) -> Option AQuick Check:
Topological sort = Kahn's Algorithm purpose [OK]
- Confusing topological sort with shortest path
- Thinking it detects cycles in undirected graphs
- Mixing with minimum spanning tree algorithms
Solution
Step 1: Identify the data structure for zero in-degree nodes
Kahn's Algorithm uses a queue to process nodes with zero incoming edges in FIFO order to maintain correct topological order.Step 2: Eliminate other options
Stack is LIFO, which can change order; HashSet does not maintain order; PriorityQueue is not required for basic Kahn's Algorithm.Final Answer:
Queue -> Option AQuick Check:
Zero in-degree nodes stored in queue [OK]
- Using stack instead of queue
- Choosing unordered sets instead of ordered structures
- Confusing with priority queue usage
Graph edges: 5->0, 5->2, 4->0, 4->1, 2->3, 3->1 // After running Kahn's Algorithm, print the topological order.
Solution
Step 1: Calculate in-degree and start nodes
Nodes 4 and 5 have zero in-degree. Start queue with [4,5] (assuming ascending order).Step 2: Process nodes in queue
Process 4: output [4], reduce 0 to 1, 1 to 1. Process 5: output [4,5], reduce 0 to 0 (add 0), 2 to 0 (add 2); queue=[0,2]. Process 0: [4,5,0], no neighbors. Process 2: [4,5,0,2], reduce 3 to 0 (add 3). Process 3: [4,5,0,2,3], reduce 1 to 0 (add 1). Process 1: [4,5,0,2,3,1].Final Answer:
[4, 5, 0, 2, 3, 1] -> Option CQuick Check:
Topological order = [4,5,0,2,3,1] [OK]
- Mixing order of nodes with zero in-degree
- Not updating in-degree after removing edges
- Adding nodes to queue too early or late
while (!queue.isEmpty()) {
int node = queue.poll();
result.add(node);
for (int neighbor : graph.get(node)) {
inDegree[neighbor]--;
if (inDegree[node] == 0) {
queue.add(neighbor);
}
}Solution
Step 1: Analyze the in-degree update and condition
After decrementing inDegree[neighbor], the code incorrectly checks if inDegree[node] == 0 instead of inDegree[neighbor] == 0.Step 2: Correct the condition to add neighbors with zero in-degree
The correct condition is if (inDegree[neighbor] == 0) to add that neighbor to the queue for processing.Final Answer:
Incorrect check: should check inDegree[neighbor] == 0, not inDegree[node] -> Option DQuick Check:
Check zero in-degree on neighbor, not current node [OK]
- Checking in-degree of wrong node
- Using stack instead of queue
- Clearing result inside loop mistakenly
Solution
Step 1: Identify nodes with zero in-degree and dependencies
Node 1 has zero in-degree. Nodes 2 and 3 depend on 1; 4 depends on 2 and 3; 5 depends on 4; 6 depends on 5.Step 2: Validate each option for correct order
[1, 3, 2, 4, 5, 6] respects dependencies: 1 before 2 and 3, 3 and 2 before 4, 4 before 5, 5 before 6. [1, 2, 3, 4, 6, 5] places 6 before 5, invalid. [6, 5, 4, 3, 2, 1] reverses order, invalid. [1, 2, 3, 5, 4, 6] places 5 before 4, invalid.Final Answer:
[1, 3, 2, 4, 5, 6] -> Option BQuick Check:
Dependencies respected in order D [OK]
- Placing dependent nodes before their parents
- Reversing the order of edges
- Ignoring multiple valid topological orders
Ready to prove it?
Pass the test and this pattern moves unknown
